@stigmer/runner 3.0.9-dev.20260615153829 → 3.1.0

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 (329) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/__test-utils__/approval-contract/types.d.ts +174 -0
  3. package/dist/__test-utils__/approval-contract/types.js +24 -0
  4. package/dist/__test-utils__/approval-contract/types.js.map +1 -0
  5. package/dist/activities/call-agent-status.d.ts +19 -1
  6. package/dist/activities/call-agent-status.js +64 -5
  7. package/dist/activities/call-agent-status.js.map +1 -1
  8. package/dist/activities/call-llm.js +19 -53
  9. package/dist/activities/call-llm.js.map +1 -1
  10. package/dist/activities/classify-tool-approvals.d.ts +24 -0
  11. package/dist/activities/classify-tool-approvals.js +69 -17
  12. package/dist/activities/classify-tool-approvals.js.map +1 -1
  13. package/dist/activities/discover-mcp-server.d.ts +7 -0
  14. package/dist/activities/discover-mcp-server.js +11 -1
  15. package/dist/activities/discover-mcp-server.js.map +1 -1
  16. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +140 -0
  17. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +130 -0
  18. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -0
  19. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.d.ts +18 -0
  20. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +123 -0
  21. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -0
  22. package/dist/activities/execute-cursor/approval-policy.d.ts +17 -61
  23. package/dist/activities/execute-cursor/approval-policy.js +8 -120
  24. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  25. package/dist/activities/execute-cursor/approval-state.d.ts +219 -9
  26. package/dist/activities/execute-cursor/approval-state.js +233 -17
  27. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  28. package/dist/activities/execute-cursor/capture-flow.d.ts +127 -0
  29. package/dist/activities/execute-cursor/capture-flow.js +234 -0
  30. package/dist/activities/execute-cursor/capture-flow.js.map +1 -0
  31. package/dist/activities/execute-cursor/cas-observations.d.ts +96 -0
  32. package/dist/activities/execute-cursor/cas-observations.js +184 -0
  33. package/dist/activities/execute-cursor/cas-observations.js.map +1 -0
  34. package/dist/activities/execute-cursor/command-provenance.d.ts +62 -0
  35. package/dist/activities/execute-cursor/command-provenance.js +128 -0
  36. package/dist/activities/execute-cursor/command-provenance.js.map +1 -0
  37. package/dist/activities/execute-cursor/exact-apply.d.ts +110 -0
  38. package/dist/activities/execute-cursor/exact-apply.js +204 -0
  39. package/dist/activities/execute-cursor/exact-apply.js.map +1 -0
  40. package/dist/activities/execute-cursor/hook-script.d.ts +53 -24
  41. package/dist/activities/execute-cursor/hook-script.js +310 -47
  42. package/dist/activities/execute-cursor/hook-script.js.map +1 -1
  43. package/dist/activities/execute-cursor/index.d.ts +8 -1
  44. package/dist/activities/execute-cursor/index.js +500 -64
  45. package/dist/activities/execute-cursor/index.js.map +1 -1
  46. package/dist/activities/execute-cursor/message-translator.d.ts +258 -11
  47. package/dist/activities/execute-cursor/message-translator.js +836 -90
  48. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  49. package/dist/activities/execute-cursor/prompt-builder.d.ts +20 -23
  50. package/dist/activities/execute-cursor/prompt-builder.js +74 -15
  51. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  52. package/dist/activities/execute-cursor/workspace-setup.d.ts +17 -0
  53. package/dist/activities/execute-cursor/workspace-setup.js +212 -33
  54. package/dist/activities/execute-cursor/workspace-setup.js.map +1 -1
  55. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.d.ts +19 -0
  56. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js +143 -0
  57. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js.map +1 -0
  58. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +88 -0
  59. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +81 -0
  60. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -0
  61. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +47 -0
  62. package/dist/activities/execute-deep-agent/approval-file-change.js +68 -0
  63. package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -0
  64. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +8 -1
  65. package/dist/activities/execute-deep-agent/attachment-injector.js +7 -7
  66. package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
  67. package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +42 -0
  68. package/dist/activities/execute-deep-agent/cas-capture-backend.js +47 -0
  69. package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -0
  70. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +79 -0
  71. package/dist/activities/execute-deep-agent/cas-capture-observer.js +112 -0
  72. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -0
  73. package/dist/activities/execute-deep-agent/hitl.d.ts +16 -3
  74. package/dist/activities/execute-deep-agent/hitl.js +11 -3
  75. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  76. package/dist/activities/execute-deep-agent/index.d.ts +2 -1
  77. package/dist/activities/execute-deep-agent/index.js +393 -33
  78. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  79. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +7 -1
  80. package/dist/activities/execute-deep-agent/inline-publisher.js +23 -2
  81. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
  82. package/dist/activities/execute-deep-agent/setup.d.ts +53 -2
  83. package/dist/activities/execute-deep-agent/setup.js +149 -92
  84. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  85. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +36 -0
  86. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +56 -0
  87. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +1 -0
  88. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +34 -1
  89. package/dist/activities/execute-deep-agent/status-builder-shared.js +26 -25
  90. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  91. package/dist/activities/execute-deep-agent/status-builder.d.ts +17 -5
  92. package/dist/activities/execute-deep-agent/status-builder.js +44 -3
  93. package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
  94. package/dist/activities/execute-deep-agent/streaming-side-effects.js +2 -19
  95. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/streaming.js +3 -15
  97. package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
  98. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -7
  99. package/dist/activities/execute-deep-agent/subagent-transformer.js +23 -7
  100. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  101. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +30 -3
  102. package/dist/activities/execute-deep-agent/subagent-wiring.js +29 -3
  103. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  104. package/dist/activities/execute-deep-agent/v3-status-builder.js +32 -2
  105. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  106. package/dist/claimcheck/payload-codec.js +9 -5
  107. package/dist/claimcheck/payload-codec.js.map +1 -1
  108. package/dist/client/stigmer-client.d.ts +2 -0
  109. package/dist/client/stigmer-client.js +2 -0
  110. package/dist/client/stigmer-client.js.map +1 -1
  111. package/dist/middleware/approval-gate.d.ts +85 -4
  112. package/dist/middleware/approval-gate.js +165 -38
  113. package/dist/middleware/approval-gate.js.map +1 -1
  114. package/dist/middleware/types.d.ts +2 -5
  115. package/dist/shared/activity-input.d.ts +43 -0
  116. package/dist/shared/activity-input.js +17 -0
  117. package/dist/shared/activity-input.js.map +1 -0
  118. package/dist/shared/approval-canonicalize.d.ts +19 -0
  119. package/dist/shared/approval-canonicalize.js +119 -0
  120. package/dist/shared/approval-canonicalize.js.map +1 -0
  121. package/dist/shared/approval-fingerprint.d.ts +106 -0
  122. package/dist/shared/approval-fingerprint.js +113 -0
  123. package/dist/shared/approval-fingerprint.js.map +1 -0
  124. package/dist/shared/approval-policy.d.ts +182 -12
  125. package/dist/shared/approval-policy.js +213 -27
  126. package/dist/shared/approval-policy.js.map +1 -1
  127. package/dist/shared/args-preview.d.ts +52 -0
  128. package/dist/shared/args-preview.js +93 -0
  129. package/dist/shared/args-preview.js.map +1 -0
  130. package/dist/shared/artifact-storage.d.ts +19 -1
  131. package/dist/shared/artifact-storage.js +48 -11
  132. package/dist/shared/artifact-storage.js.map +1 -1
  133. package/dist/shared/file-change.d.ts +44 -0
  134. package/dist/shared/file-change.js +57 -0
  135. package/dist/shared/file-change.js.map +1 -0
  136. package/dist/shared/file-tools.d.ts +107 -0
  137. package/dist/shared/file-tools.js +168 -0
  138. package/dist/shared/file-tools.js.map +1 -0
  139. package/dist/shared/filereview/capture.d.ts +202 -0
  140. package/dist/shared/filereview/capture.js +498 -0
  141. package/dist/shared/filereview/capture.js.map +1 -0
  142. package/dist/shared/filereview/cas-substrate.d.ts +190 -0
  143. package/dist/shared/filereview/cas-substrate.js +284 -0
  144. package/dist/shared/filereview/cas-substrate.js.map +1 -0
  145. package/dist/shared/filereview/digest.d.ts +40 -0
  146. package/dist/shared/filereview/digest.js +66 -0
  147. package/dist/shared/filereview/digest.js.map +1 -0
  148. package/dist/shared/filereview/events.d.ts +170 -0
  149. package/dist/shared/filereview/events.js +298 -0
  150. package/dist/shared/filereview/events.js.map +1 -0
  151. package/dist/shared/filereview/git-substrate.d.ts +175 -0
  152. package/dist/shared/filereview/git-substrate.js +439 -0
  153. package/dist/shared/filereview/git-substrate.js.map +1 -0
  154. package/dist/shared/filereview/index.d.ts +11 -0
  155. package/dist/shared/filereview/index.js +12 -0
  156. package/dist/shared/filereview/index.js.map +1 -0
  157. package/dist/shared/filereview/secret-paths.d.ts +63 -0
  158. package/dist/shared/filereview/secret-paths.js +105 -0
  159. package/dist/shared/filereview/secret-paths.js.map +1 -0
  160. package/dist/shared/fingerprint-secret.d.ts +26 -0
  161. package/dist/shared/fingerprint-secret.js +47 -0
  162. package/dist/shared/fingerprint-secret.js.map +1 -0
  163. package/dist/shared/model-client.d.ts +51 -0
  164. package/dist/shared/model-client.js +77 -0
  165. package/dist/shared/model-client.js.map +1 -0
  166. package/dist/shared/plan-artifact.js +0 -2
  167. package/dist/shared/plan-artifact.js.map +1 -1
  168. package/dist/shared/status-offload.d.ts +83 -9
  169. package/dist/shared/status-offload.js +399 -79
  170. package/dist/shared/status-offload.js.map +1 -1
  171. package/dist/shared/status.js +14 -1
  172. package/dist/shared/status.js.map +1 -1
  173. package/dist/shared/tool-kind.d.ts +19 -0
  174. package/dist/shared/tool-kind.js +13 -0
  175. package/dist/shared/tool-kind.js.map +1 -1
  176. package/dist/shared/tool-row.d.ts +88 -0
  177. package/dist/shared/tool-row.js +127 -0
  178. package/dist/shared/tool-row.js.map +1 -0
  179. package/dist/shared/workspace/platform-dir.d.ts +25 -0
  180. package/dist/shared/workspace/platform-dir.js +38 -2
  181. package/dist/shared/workspace/platform-dir.js.map +1 -1
  182. package/dist/workflows/call-agent-orchestrator.js +56 -7
  183. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  184. package/dist/workflows/connect-mcp-server.d.ts +50 -0
  185. package/dist/workflows/connect-mcp-server.js +136 -15
  186. package/dist/workflows/connect-mcp-server.js.map +1 -1
  187. package/dist/workflows/types.d.ts +8 -0
  188. package/package.json +2 -2
  189. package/src/__test-utils__/approval-contract/contract.ts +224 -0
  190. package/src/__test-utils__/approval-contract/types.ts +179 -0
  191. package/src/__test-utils__/fake-artifact-storage.ts +72 -0
  192. package/src/__tests__/approval-gateway-contract.test.ts +29 -0
  193. package/src/__tests__/claimcheck-codec.test.ts +16 -53
  194. package/src/__tests__/golden-e2e.test.ts +2 -0
  195. package/src/__tests__/runner-token-coordinator.test.ts +3 -3
  196. package/src/activities/__tests__/call-agent-status.test.ts +135 -0
  197. package/src/activities/__tests__/call-llm.test.ts +1 -1
  198. package/src/activities/__tests__/classify-tool-approvals.test.ts +208 -1
  199. package/src/activities/__tests__/discover-mcp-server.test.ts +30 -0
  200. package/src/activities/__tests__/workflow-event-activities.test.ts +2 -1
  201. package/src/activities/call-agent-status.ts +74 -4
  202. package/src/activities/call-llm.ts +18 -63
  203. package/src/activities/classify-tool-approvals.ts +101 -19
  204. package/src/activities/discover-mcp-server.ts +29 -1
  205. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +216 -0
  206. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +148 -0
  207. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +41 -9
  208. package/src/activities/execute-cursor/__tests__/approval-state.test.ts +292 -0
  209. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +68 -1
  210. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +1005 -0
  211. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +187 -0
  212. package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +97 -0
  213. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +240 -0
  214. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +203 -0
  215. package/src/activities/execute-cursor/__tests__/exact-apply.test.ts +375 -0
  216. package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +1294 -24
  217. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +446 -0
  218. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +384 -110
  219. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +171 -25
  220. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +189 -0
  221. package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +44 -23
  222. package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +190 -10
  223. package/src/activities/execute-cursor/approval-policy.ts +28 -159
  224. package/src/activities/execute-cursor/approval-state.ts +366 -18
  225. package/src/activities/execute-cursor/capture-flow.ts +323 -0
  226. package/src/activities/execute-cursor/cas-observations.ts +204 -0
  227. package/src/activities/execute-cursor/command-provenance.ts +168 -0
  228. package/src/activities/execute-cursor/exact-apply.ts +253 -0
  229. package/src/activities/execute-cursor/hook-script.ts +317 -51
  230. package/src/activities/execute-cursor/index.ts +575 -67
  231. package/src/activities/execute-cursor/message-translator.ts +963 -89
  232. package/src/activities/execute-cursor/prompt-builder.ts +80 -14
  233. package/src/activities/execute-cursor/workspace-setup.ts +257 -42
  234. package/src/activities/execute-deep-agent/__test-utils__/gateway-substrate.ts +180 -0
  235. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +134 -0
  236. package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +84 -0
  237. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +11 -24
  238. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +64 -0
  239. package/src/activities/execute-deep-agent/__tests__/cas-capture-observer.test.ts +163 -0
  240. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +8 -5
  241. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +342 -0
  242. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +284 -0
  243. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +14 -36
  244. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +31 -13
  245. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +349 -0
  246. package/src/activities/execute-deep-agent/__tests__/stamp-flowed-rows.test.ts +119 -0
  247. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +91 -10
  248. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +9 -9
  249. package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
  250. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +213 -0
  251. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +3 -6
  252. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +84 -1
  253. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +4 -1
  254. package/src/activities/execute-deep-agent/approval-file-change.ts +80 -0
  255. package/src/activities/execute-deep-agent/attachment-injector.ts +20 -11
  256. package/src/activities/execute-deep-agent/cas-capture-backend.ts +66 -0
  257. package/src/activities/execute-deep-agent/cas-capture-observer.ts +125 -0
  258. package/src/activities/execute-deep-agent/hitl.ts +23 -7
  259. package/src/activities/execute-deep-agent/index.ts +463 -40
  260. package/src/activities/execute-deep-agent/inline-publisher.ts +27 -4
  261. package/src/activities/execute-deep-agent/setup.ts +223 -125
  262. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +64 -0
  263. package/src/activities/execute-deep-agent/status-builder-shared.ts +62 -23
  264. package/src/activities/execute-deep-agent/status-builder.ts +63 -8
  265. package/src/activities/execute-deep-agent/streaming-side-effects.ts +2 -16
  266. package/src/activities/execute-deep-agent/streaming.ts +3 -13
  267. package/src/activities/execute-deep-agent/subagent-transformer.ts +53 -13
  268. package/src/activities/execute-deep-agent/subagent-wiring.ts +50 -3
  269. package/src/activities/execute-deep-agent/v3-status-builder.ts +36 -2
  270. package/src/claimcheck/payload-codec.ts +8 -8
  271. package/src/client/stigmer-client.ts +9 -1
  272. package/src/middleware/__tests__/approval-gate.test.ts +488 -4
  273. package/src/middleware/approval-gate.ts +247 -38
  274. package/src/middleware/types.ts +5 -5
  275. package/src/shared/__tests__/activity-input.test.ts +78 -0
  276. package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
  277. package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
  278. package/src/shared/__tests__/approval-policy.test.ts +274 -40
  279. package/src/shared/__tests__/args-preview.test.ts +78 -0
  280. package/src/shared/__tests__/artifact-storage-extended.test.ts +62 -10
  281. package/src/shared/__tests__/artifact-storage.test.ts +123 -11
  282. package/src/shared/__tests__/file-change.test.ts +85 -0
  283. package/src/shared/__tests__/file-tools.test.ts +90 -0
  284. package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
  285. package/src/shared/__tests__/lease-scope-corpus.test.ts +56 -0
  286. package/src/shared/__tests__/model-client.test.ts +162 -0
  287. package/src/shared/__tests__/plan-artifact.test.ts +11 -26
  288. package/src/shared/__tests__/policy-source-corpus.test.ts +58 -0
  289. package/src/shared/__tests__/status-offload.test.ts +573 -16
  290. package/src/shared/__tests__/status.test.ts +4 -5
  291. package/src/shared/__tests__/tool-kind.test.ts +24 -1
  292. package/src/shared/__tests__/tool-row.test.ts +221 -0
  293. package/src/shared/activity-input.ts +57 -0
  294. package/src/shared/approval-canonicalize.ts +159 -0
  295. package/src/shared/approval-fingerprint.ts +148 -0
  296. package/src/shared/approval-policy.ts +303 -27
  297. package/src/shared/args-preview.ts +98 -0
  298. package/src/shared/artifact-storage.ts +62 -11
  299. package/src/shared/checkpointer/__tests__/http-saver.test.ts +1 -2
  300. package/src/shared/file-change.ts +64 -0
  301. package/src/shared/file-tools.ts +169 -0
  302. package/src/shared/filereview/__tests__/capture.test.ts +856 -0
  303. package/src/shared/filereview/__tests__/cas-substrate.test.ts +404 -0
  304. package/src/shared/filereview/__tests__/digest.test.ts +100 -0
  305. package/src/shared/filereview/__tests__/events.test.ts +245 -0
  306. package/src/shared/filereview/__tests__/git-substrate.test.ts +362 -0
  307. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +286 -0
  308. package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
  309. package/src/shared/filereview/capture.ts +727 -0
  310. package/src/shared/filereview/cas-substrate.ts +401 -0
  311. package/src/shared/filereview/digest.ts +83 -0
  312. package/src/shared/filereview/events.ts +449 -0
  313. package/src/shared/filereview/git-substrate.ts +555 -0
  314. package/src/shared/filereview/index.ts +60 -0
  315. package/src/shared/filereview/secret-paths.ts +121 -0
  316. package/src/shared/fingerprint-secret.ts +53 -0
  317. package/src/shared/model-client.ts +122 -0
  318. package/src/shared/plan-artifact.ts +0 -2
  319. package/src/shared/status-offload.ts +433 -77
  320. package/src/shared/status.ts +13 -0
  321. package/src/shared/tool-kind.ts +33 -0
  322. package/src/shared/tool-row.ts +135 -0
  323. package/src/shared/workspace/platform-dir.ts +41 -2
  324. package/src/workflow-engine/__tests__/golden-execution.test.ts +35 -18
  325. package/src/workflow-engine/__tests__/tasks/try.test.ts +1 -1
  326. package/src/workflows/__tests__/connect-mcp-server.test.ts +304 -29
  327. package/src/workflows/call-agent-orchestrator.ts +53 -6
  328. package/src/workflows/connect-mcp-server.ts +179 -24
  329. package/src/workflows/types.ts +8 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Approval fingerprint — the exact-match enforcement identity for the HITL Tool
3
+ * Execution Gateway (Phase 2).
4
+ *
5
+ * A fingerprint is `HMAC-SHA256(key, canonicalForm)` over a canonicalized tool
6
+ * action (see {@link file://./approval-canonicalize.ts}). It answers exactly one
7
+ * question at the moment of side effect: "is *this* action the one the user
8
+ * approved?" An approval is bound to the canonical identity of the action, not to
9
+ * the transient id of the proposing tool call, so a re-driven action that differs
10
+ * from what was approved is re-asked — never silently executed.
11
+ *
12
+ * Why HMAC and not a bare SHA-256 (binding canonical decision,
13
+ * design-decisions/approval-fingerprint-vs-march-rollback.md, Rule 4): the
14
+ * fingerprint is an authorization token, not a correlation key. Keying it under a
15
+ * Stigmer-held secret means a model (or a compromised workspace) cannot forge a
16
+ * value that the gateway will accept. In Phase 2 the fingerprint is
17
+ * recompute-and-compare at one trusted layer (no bearer token crosses a wire), so
18
+ * the anti-forgery property is forward-looking — it earns its keep when a lease
19
+ * later becomes a server-issued bearer token (Phase 7). We pay the small cost now
20
+ * to avoid a migration that re-keys every persisted approval later.
21
+ *
22
+ * Two fidelities share this one canonicalization core, because the two
23
+ * enforcement substrates differ (see the Phase-2 plan, "two enforcement
24
+ * substrates, not one"):
25
+ *
26
+ * - FULL ({@link computeApprovalFingerprint}) — HMAC over the full canonical
27
+ * action (tool + paths + shellCommand + args). Used by the in-process
28
+ * deep-agent gateway, where approve-time and execute-time observe the same
29
+ * arg shape (LangGraph checkpoint replay), so the action can be matched at
30
+ * full fidelity.
31
+ * - COARSE ({@link computeCoarseApprovalFingerprint}) — HMAC over
32
+ * (category, salient) only. Used by the out-of-process Cursor deny-oracle
33
+ * hook, whose stdin payload names the same action with a different taxonomy
34
+ * (`Write` vs `edit`, `file_path` vs `path`) and cannot reproduce the full
35
+ * args. The coarse projection is the documented, substrate-forced coarsening
36
+ * that lets the hook-side and stream-side fingerprints agree; it is the
37
+ * successor identity for execute-cursor's grant token.
38
+ *
39
+ * The fingerprint is enforcement-only and never a correlation key — correlation
40
+ * stays `approval_request_id` + `tool_call_id`.
41
+ */
42
+ import { type BinaryLike } from "node:crypto";
43
+ import { type ToolActionInput } from "./approval-canonicalize.js";
44
+ /**
45
+ * Version tag prefixed to every fingerprint. Bumping it is the migration lever
46
+ * if the canonical form or the MAC primitive ever changes: an old lease and a
47
+ * new computation will not compare equal, so a version skew re-asks (safe) rather
48
+ * than silently mismatching. Keep in lockstep with the Go/Java editions.
49
+ */
50
+ export declare const APPROVAL_FINGERPRINT_VERSION = "v1";
51
+ /** The HMAC key. Raw bytes (Buffer) in production; a UTF-8 string in tests. */
52
+ export type FingerprintKey = BinaryLike;
53
+ /**
54
+ * Full-fidelity fingerprint for the in-process deep-agent gateway. Distinct
55
+ * actions (different tool, paths, command, or args) yield distinct fingerprints;
56
+ * the same action is byte-stable across re-invocations.
57
+ */
58
+ export declare function computeApprovalFingerprint(key: FingerprintKey, input: ToolActionInput): string;
59
+ /**
60
+ * The substrate-coarsened identity of a tool action — the only fidelity the
61
+ * Cursor deny-oracle hook can reproduce from its stdin payload.
62
+ *
63
+ * Mirrors execute-cursor's `toolIdentity` so the two converge on one definition:
64
+ * - `tool` is the cross-taxonomy {@link toolApprovalCategory} (`write`/`delete`/
65
+ * `shell`) for gated built-ins, the tool name for MCP tools (whose name is
66
+ * stable across layers), or the trimmed tool name for non-gated built-ins
67
+ * (never lease-matched, so the fallback is harmless).
68
+ * - `salient` is the single resource the action targets (a normalized path or the
69
+ * shell command), reusing the full form's normalization so one rule governs
70
+ * both fidelities. Empty for MCP tools, which are matched by `tool` alone.
71
+ */
72
+ export interface CoarseToolIdentity {
73
+ tool: string;
74
+ mcpServerSlug: string;
75
+ salient: string;
76
+ }
77
+ export declare function coarseToolIdentity(input: ToolActionInput): CoarseToolIdentity;
78
+ /**
79
+ * Fingerprint an already-reduced {@link CoarseToolIdentity}. Split out from
80
+ * {@link computeCoarseApprovalFingerprint} so a substrate that has *already*
81
+ * reduced a tool call to its (tool, mcpServerSlug, salient) identity — the Cursor
82
+ * harness, whose hook and stream both key on a raw, un-normalized salient that
83
+ * the bash hook can reproduce without a workspace root — can fingerprint that
84
+ * exact identity through the one shared HMAC+canonical-JSON path, instead of
85
+ * re-deriving the salient via {@link canonicalizeToolAction} (which normalizes
86
+ * paths and would diverge from the hook's raw value).
87
+ */
88
+ export declare function fingerprintCoarseIdentity(key: FingerprintKey, identity: CoarseToolIdentity): string;
89
+ /**
90
+ * Coarse fingerprint for the out-of-process Cursor hook. By construction, two
91
+ * actions that name the same operation in different taxonomies (`Write` vs
92
+ * `edit`) over the same resource collapse to one fingerprint — this is what makes
93
+ * the hook-side (deny/grant) and stream-side (reconciliation) values agree.
94
+ */
95
+ export declare function computeCoarseApprovalFingerprint(key: FingerprintKey, input: ToolActionInput): string;
96
+ /**
97
+ * Derive the per-execution fingerprint key from a runner-held master secret.
98
+ *
99
+ * The key is scoped to one `execution_id`: stable across Temporal re-invocations
100
+ * of the same execution (the gateway approves on one invocation and enforces on
101
+ * the next), and isolated between executions so a fingerprint approved for one
102
+ * cannot be replayed against another. The master-secret source is wired when the
103
+ * gateway first consumes the fingerprint (Slices C/D); until then this is
104
+ * exercised only by tests against a fixed master secret.
105
+ */
106
+ export declare function deriveExecutionFingerprintKey(masterSecret: FingerprintKey, executionId: string): Buffer;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Approval fingerprint — the exact-match enforcement identity for the HITL Tool
3
+ * Execution Gateway (Phase 2).
4
+ *
5
+ * A fingerprint is `HMAC-SHA256(key, canonicalForm)` over a canonicalized tool
6
+ * action (see {@link file://./approval-canonicalize.ts}). It answers exactly one
7
+ * question at the moment of side effect: "is *this* action the one the user
8
+ * approved?" An approval is bound to the canonical identity of the action, not to
9
+ * the transient id of the proposing tool call, so a re-driven action that differs
10
+ * from what was approved is re-asked — never silently executed.
11
+ *
12
+ * Why HMAC and not a bare SHA-256 (binding canonical decision,
13
+ * design-decisions/approval-fingerprint-vs-march-rollback.md, Rule 4): the
14
+ * fingerprint is an authorization token, not a correlation key. Keying it under a
15
+ * Stigmer-held secret means a model (or a compromised workspace) cannot forge a
16
+ * value that the gateway will accept. In Phase 2 the fingerprint is
17
+ * recompute-and-compare at one trusted layer (no bearer token crosses a wire), so
18
+ * the anti-forgery property is forward-looking — it earns its keep when a lease
19
+ * later becomes a server-issued bearer token (Phase 7). We pay the small cost now
20
+ * to avoid a migration that re-keys every persisted approval later.
21
+ *
22
+ * Two fidelities share this one canonicalization core, because the two
23
+ * enforcement substrates differ (see the Phase-2 plan, "two enforcement
24
+ * substrates, not one"):
25
+ *
26
+ * - FULL ({@link computeApprovalFingerprint}) — HMAC over the full canonical
27
+ * action (tool + paths + shellCommand + args). Used by the in-process
28
+ * deep-agent gateway, where approve-time and execute-time observe the same
29
+ * arg shape (LangGraph checkpoint replay), so the action can be matched at
30
+ * full fidelity.
31
+ * - COARSE ({@link computeCoarseApprovalFingerprint}) — HMAC over
32
+ * (category, salient) only. Used by the out-of-process Cursor deny-oracle
33
+ * hook, whose stdin payload names the same action with a different taxonomy
34
+ * (`Write` vs `edit`, `file_path` vs `path`) and cannot reproduce the full
35
+ * args. The coarse projection is the documented, substrate-forced coarsening
36
+ * that lets the hook-side and stream-side fingerprints agree; it is the
37
+ * successor identity for execute-cursor's grant token.
38
+ *
39
+ * The fingerprint is enforcement-only and never a correlation key — correlation
40
+ * stays `approval_request_id` + `tool_call_id`.
41
+ */
42
+ import { createHmac } from "node:crypto";
43
+ import { canonicalJson, canonicalToolActionJson, canonicalizeToolAction, } from "./approval-canonicalize.js";
44
+ import { toolApprovalCategory } from "./tool-kind.js";
45
+ /**
46
+ * Version tag prefixed to every fingerprint. Bumping it is the migration lever
47
+ * if the canonical form or the MAC primitive ever changes: an old lease and a
48
+ * new computation will not compare equal, so a version skew re-asks (safe) rather
49
+ * than silently mismatching. Keep in lockstep with the Go/Java editions.
50
+ */
51
+ export const APPROVAL_FINGERPRINT_VERSION = "v1";
52
+ /**
53
+ * Full-fidelity fingerprint for the in-process deep-agent gateway. Distinct
54
+ * actions (different tool, paths, command, or args) yield distinct fingerprints;
55
+ * the same action is byte-stable across re-invocations.
56
+ */
57
+ export function computeApprovalFingerprint(key, input) {
58
+ return tagged(hmacHex(key, canonicalToolActionJson(input)));
59
+ }
60
+ export function coarseToolIdentity(input) {
61
+ const canonical = canonicalizeToolAction(input);
62
+ if (canonical.mcpServerSlug) {
63
+ return { tool: input.toolName.trim(), mcpServerSlug: canonical.mcpServerSlug, salient: "" };
64
+ }
65
+ const category = toolApprovalCategory(input.toolName);
66
+ return {
67
+ tool: category ?? input.toolName.trim(),
68
+ mcpServerSlug: "",
69
+ salient: canonical.paths[0] || canonical.shellCommand || "",
70
+ };
71
+ }
72
+ /**
73
+ * Fingerprint an already-reduced {@link CoarseToolIdentity}. Split out from
74
+ * {@link computeCoarseApprovalFingerprint} so a substrate that has *already*
75
+ * reduced a tool call to its (tool, mcpServerSlug, salient) identity — the Cursor
76
+ * harness, whose hook and stream both key on a raw, un-normalized salient that
77
+ * the bash hook can reproduce without a workspace root — can fingerprint that
78
+ * exact identity through the one shared HMAC+canonical-JSON path, instead of
79
+ * re-deriving the salient via {@link canonicalizeToolAction} (which normalizes
80
+ * paths and would diverge from the hook's raw value).
81
+ */
82
+ export function fingerprintCoarseIdentity(key, identity) {
83
+ return tagged(hmacHex(key, canonicalJson(identity)));
84
+ }
85
+ /**
86
+ * Coarse fingerprint for the out-of-process Cursor hook. By construction, two
87
+ * actions that name the same operation in different taxonomies (`Write` vs
88
+ * `edit`) over the same resource collapse to one fingerprint — this is what makes
89
+ * the hook-side (deny/grant) and stream-side (reconciliation) values agree.
90
+ */
91
+ export function computeCoarseApprovalFingerprint(key, input) {
92
+ return fingerprintCoarseIdentity(key, coarseToolIdentity(input));
93
+ }
94
+ /**
95
+ * Derive the per-execution fingerprint key from a runner-held master secret.
96
+ *
97
+ * The key is scoped to one `execution_id`: stable across Temporal re-invocations
98
+ * of the same execution (the gateway approves on one invocation and enforces on
99
+ * the next), and isolated between executions so a fingerprint approved for one
100
+ * cannot be replayed against another. The master-secret source is wired when the
101
+ * gateway first consumes the fingerprint (Slices C/D); until then this is
102
+ * exercised only by tests against a fixed master secret.
103
+ */
104
+ export function deriveExecutionFingerprintKey(masterSecret, executionId) {
105
+ return createHmac("sha256", masterSecret).update(executionId, "utf8").digest();
106
+ }
107
+ function hmacHex(key, canonical) {
108
+ return createHmac("sha256", key).update(canonical, "utf8").digest("hex");
109
+ }
110
+ function tagged(mac) {
111
+ return `${APPROVAL_FINGERPRINT_VERSION}:${mac}`;
112
+ }
113
+ //# sourceMappingURL=approval-fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-fingerprint.js","sourceRoot":"","sources":["../../src/shared/approval-fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,sBAAsB,GAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAKjD;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,GAAmB,EAAE,KAAsB;IACpF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAqBD,MAAM,UAAU,kBAAkB,CAAC,KAAsB;IACvD,MAAM,SAAS,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC;QAC5B,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC9F,CAAC;IACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtD,OAAO;QACL,IAAI,EAAE,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE;QACvC,aAAa,EAAE,EAAE;QACjB,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,YAAY,IAAI,EAAE;KAC5D,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAAmB,EAAE,QAA4B;IACzF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,GAAmB,EAAE,KAAsB;IAC1F,OAAO,yBAAyB,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAAC,YAA4B,EAAE,WAAmB;IAC7F,OAAO,UAAU,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;AACjF,CAAC;AAED,SAAS,OAAO,CAAC,GAAmB,EAAE,SAAiB;IACrD,OAAO,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,MAAM,CAAC,GAAW;IACzB,OAAO,GAAG,4BAA4B,IAAI,GAAG,EAAE,CAAC;AAClD,CAAC"}
@@ -5,41 +5,211 @@
5
5
  * 1. McpServerStatus.tool_approvals — system-generated defaults
6
6
  * 2. McpServerSpec.pinned_tool_approvals — manual overrides
7
7
  * 3. McpServerUsage.tool_approval_overrides — per-agent customization
8
- * 4. AgentExecutionSpec.auto_approve_all — runtime bypass
8
+ * 4. Active approval leases the runtime bypass, now SCOPED: the pre-armed
9
+ * spec.auto_approve_all is a whole-run global bypass, while an interactive
10
+ * APPROVE_ALL ("approve all of this kind") grants a run-lifetime lease for
11
+ * only that action's scope (its built-in category, or its MCP server). See
12
+ * {@link ActiveLeases}.
9
13
  *
10
14
  * Used by both ExecuteCursor (hook-deny model) and ExecuteDeepAgent
11
15
  * (middleware interruptOn model) to determine which tools need approval.
12
16
  */
13
17
  import type { ToolApprovalOverride } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
14
18
  import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
19
+ import { ApprovalPolicySource } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
20
+ import { type ToolApprovalCategory } from "./tool-kind.js";
15
21
  import type { ResolvedMcpServer } from "./mcp-resolver.js";
16
22
  /**
17
- * Returns true if any tool call in the execution history (root or sub-agent)
18
- * carries an APPROVE_ALL decision.
23
+ * The set of run-lifetime approval leases active for an execution.
19
24
  *
20
- * This is the runner-side realization of the APPROVE_ALL contract (see the
21
- * ApprovalAction doc in enum.proto): once a user has chosen "approve and don't
22
- * ask again" at any gate, the rest of THIS execution runs un-gated exactly as
23
- * if spec.auto_approve_all were true. Both harnesses (native deepagents and
24
- * cursor) call this so the behavior is defined in exactly one place.
25
+ * A lease is the scoped successor to the old all-or-nothing "approve all". When
26
+ * a user chooses APPROVE_ALL ("approve and don't ask again") at a gate it no
27
+ * longer disables the entire gate it grants a lease for ONLY that action's
28
+ * scope, for the remainder of THIS execution: a mutating built-in category
29
+ * ({@link ToolApprovalCategory}) for a built-in tool, or an MCP server slug for
30
+ * an MCP tool. A different class of action proposed later is still gated.
31
+ *
32
+ * This is the DERIVED form of the lease — it is not (yet) a persisted proto.
33
+ * Each lease rides the `ToolCall.approval_action == APPROVE_ALL` decision that
34
+ * is already persisted and preserved (Go PreserveApprovalFields / Java
35
+ * ApprovalFieldPreserver), and its scope is recomputed on read from the tool's
36
+ * name + mcp_server_slug. Keeping it derived means one source of truth with
37
+ * nothing to drift; a persisted/transmitted `ApprovalLease` proto is warranted
38
+ * only once a lease must cross a trust boundary (a later phase).
39
+ *
40
+ * `global` is the one remaining UNSCOPED bypass: the deliberate, pre-armed
41
+ * spec.auto_approve_all ("trust this whole run", set before the run via
42
+ * CLI/API/CI). It is intentionally distinct from the interactive scoped leases.
43
+ */
44
+ export interface ActiveLeases {
45
+ /** Pre-armed spec.auto_approve_all: the whole gate is inert for the run. */
46
+ readonly global: boolean;
47
+ /** Built-in approval categories with a run-lifetime lease. */
48
+ readonly categories: ReadonlySet<ToolApprovalCategory>;
49
+ /** MCP server slugs with a run-lifetime lease (covers all of the server's tools). */
50
+ readonly servers: ReadonlySet<string>;
51
+ }
52
+ /**
53
+ * The class an APPROVE_ALL leases for a single tool call: an MCP tool leases its
54
+ * whole `server`, a gated built-in leases its `category`. `undefined` means the
55
+ * tool has no leasable scope (a read-only built-in, an unknown name).
56
+ *
57
+ * A discriminated union (not a `{ category?, server? }` bag) so callers cannot
58
+ * construct or observe the impossible "both set" / "neither set" states.
59
+ */
60
+ export type LeaseScope = {
61
+ readonly kind: "category";
62
+ readonly category: ToolApprovalCategory;
63
+ } | {
64
+ readonly kind: "server";
65
+ readonly server: string;
66
+ };
67
+ /**
68
+ * Reduce a single tool call to the scope its APPROVE_ALL would lease — the core
69
+ * of {@link deriveActiveLeases}, extracted so the cross-edition lease-scope
70
+ * corpus (apis/testdata/hitl/lease-scope) can exercise it directly.
71
+ *
72
+ * The MCP server slug takes precedence over the built-in category and is used
73
+ * RAW (the server's identity, not case-folded), matching the Go
74
+ * {@link DeriveLeaseScope} and Java {@link LeaseScope.deriveKey} byte-for-byte.
75
+ * The category lookup reuses {@link toolApprovalCategory}, the shared oracle, so
76
+ * a built-in resolves to write/delete/shell (read-only built-ins are ungated and
77
+ * return `undefined`).
78
+ */
79
+ export declare function deriveLeaseScope(toolName: string, mcpServerSlug: string): LeaseScope | undefined;
80
+ /**
81
+ * Derive the active approval leases for an execution.
82
+ *
83
+ * The scoped successor to the former all-or-nothing hasApproveAllDecision:
84
+ * instead of "any APPROVE_ALL anywhere disables the whole gate", each
85
+ * APPROVE_ALL decision is reduced (via {@link deriveLeaseScope}) to the SCOPE of
86
+ * the tool it was made on — the built-in category for a built-in tool (read-only
87
+ * tools are never gated, so a built-in lease is always write/delete/shell), or
88
+ * the MCP server slug for an MCP tool — and only that scope is auto-approved for
89
+ * the rest of the run.
90
+ *
91
+ * Scans root and sub-agent tool calls so a lease granted anywhere applies
92
+ * execution-wide (matching the prior cross-sub-agent behavior, now bounded by
93
+ * scope). Both harnesses call this so the contract is defined in exactly one
94
+ * place. The scope derivation reuses {@link toolApprovalCategory}, the same
95
+ * corpus-tested oracle the Go and Java editions mirror, so the backend's
96
+ * scope-aware bulk-approve and this runner-side evaluation can never disagree.
97
+ */
98
+ export declare function deriveActiveLeases(execution: AgentExecution): ActiveLeases;
99
+ /**
100
+ * Provenance of a gate decision: which policy layer (or decision point) is
101
+ * responsible for the final requires-approval verdict.
102
+ *
103
+ * Mirrors the proto {@link ApprovalPolicySource} one for one (see
104
+ * {@link toProtoPolicySource}); persisted on `ToolCall.approval_policy_source`
105
+ * so every authorization is auditable, and still stamped on the shadow
106
+ * ExecutionReceipt as a defense-in-depth audit signal.
107
+ *
108
+ * `annotation_destructive_tighten` is first-class: the connect-time tightener
109
+ * (see applyDestructiveHintTightener) marks its force-gated entries with
110
+ * `ToolApprovalPolicy.from_destructive_hint`, which {@link mergeApprovalPolicies}
111
+ * reads to attribute the gate to the annotation rather than collapsing it into
112
+ * the classifier default.
113
+ */
114
+ export type PolicySource = "classifier_default" | "pinned_override" | "agent_override" | "auto_approve_all" | "approval_lease" | "builtin_category" | "file_capture" | "annotation_destructive_tighten";
115
+ /**
116
+ * Monotonic identifier of the policy-engine logic that produced a decision,
117
+ * persisted on `ToolCall.policy_engine_version`. Bumped when the
118
+ * merge/classification semantics change so decisions made by different engine
119
+ * versions remain distinguishable in audits. Phase 7 made
120
+ * `annotation_destructive_tighten` a distinct, persisted source.
121
+ */
122
+ export declare const POLICY_ENGINE_VERSION = "phase-7";
123
+ /**
124
+ * Map the runner-internal {@link PolicySource} to the persisted proto
125
+ * {@link ApprovalPolicySource}. `undefined` (a tool no policy layer governs —
126
+ * e.g. a read-only built-in) maps to UNSPECIFIED, so the persisted field is left
127
+ * at its default exactly as an unclassified `tool_kind` is. The 1:1 mapping keeps
128
+ * the runner's union and the proto enum from drifting (asserted by the
129
+ * cross-edition corpus).
130
+ */
131
+ export declare function toProtoPolicySource(source: PolicySource | undefined): ApprovalPolicySource;
132
+ /**
133
+ * Derive the authorization provenance — which policy layer governs this tool —
134
+ * for persisting on `ToolCall.approval_policy_source`.
135
+ *
136
+ * This is the read-side twin of the gate's decision logic: same layered
137
+ * precedence, but it answers "which layer governs this call?" for EVERY tool
138
+ * (gated or auto-approved), so the StatusBuilders can stamp provenance on the
139
+ * tool call exactly where they stamp `tool_kind`. It returns `undefined` for a
140
+ * plain read-only built-in that no policy layer touches (the proto's
141
+ * APPROVAL_POLICY_SOURCE_UNSPECIFIED).
142
+ *
143
+ * Precedence:
144
+ * 1. Whole-run global bypass (pre-armed auto_approve_all) governs everything —
145
+ * it is *why* anything ran ungated, so it wins.
146
+ * 2. MCP tool: the merged policy carries the responsible layer when gated; an
147
+ * absent entry means the four-level chain cleared it (classifier base). A
148
+ * server-scoped lease also surfaces as an absent entry — distinguishing it
149
+ * would need the lease set threaded here and is deferred with the rest of the
150
+ * per-server lease provenance, so a lease-cleared MCP tool reads
151
+ * classifier_default (matching the gate).
152
+ * 3. Built-in: a mutating category is governed (leased → approval_lease, else
153
+ * builtin_category); a read-only built-in is governed by no layer → undefined.
154
+ */
155
+ export declare function resolveApprovalProvenance(toolName: string, serverSlug: string, policies: ReadonlyMap<string, MergedToolPolicy>, leasedCategories: ReadonlySet<ToolApprovalCategory>, globalBypass: boolean): PolicySource | undefined;
156
+ /**
157
+ * A single MCP tool's merged approval decision after evaluating all policy
158
+ * layers. This is the single, canonical shape shared by every harness; the
159
+ * Cursor harness re-exports it from here so the two harnesses can never drift.
25
160
  */
26
- export declare function hasApproveAllDecision(execution: AgentExecution): boolean;
27
161
  export interface MergedToolPolicy {
28
162
  toolName: string;
29
163
  mcpServerSlug: string;
30
164
  requiresApproval: boolean;
31
165
  approvalMessage: string;
166
+ /** Which policy layer set this verdict (provenance for the shadow receipt). */
167
+ source: PolicySource;
32
168
  }
33
169
  /**
34
170
  * Merge approval policies from all four levels into a single lookup map.
35
171
  *
36
- * Keys are "serverSlug/toolName" to avoid collisions between servers.
37
- * When autoApproveAll is true, the returned map is empty.
172
+ * Each MCP server contributes its own set of policies, so the map is keyed by
173
+ * "serverSlug/toolName" to avoid collisions between servers.
174
+ *
175
+ * Policy chain (each level overrides the previous):
176
+ * 1. status.toolApprovals — system-generated defaults; presence = requires approval
177
+ * 2. spec.pinnedToolApprovals — manual overrides; presence = requires approval
178
+ * 3. agent tool_approval_overrides — explicit boolean per tool (enable OR disable)
179
+ * 4. active leases — runtime bypass (highest priority), now scoped
180
+ *
181
+ * The map carries ONLY the tools that require approval — a tool's absence means
182
+ * "auto-approved". Leases shape that absence:
183
+ * - On a global pre-arm ({@link ActiveLeases.global}) the map is empty.
184
+ * - A server-scoped lease drops that server's tools from the map entirely. This
185
+ * single omission makes EVERY substrate treat the server as auto-approved with
186
+ * no extra code — the deep-agent gate and StatusBuilder read the map, and the
187
+ * Cursor hook's mcpToolPolicies is built from it (the hook is not itself
188
+ * server-aware, so omission is the only way to lease an MCP server there).
189
+ * Built-in CATEGORY leases are NOT applied here — built-ins are not in this map;
190
+ * they are cleared at the gate (deep-agent) and the hook (Cursor) instead.
191
+ *
192
+ * Used by both ExecuteCursor (hook-deny model) and ExecuteDeepAgent (middleware
193
+ * interruptOn model), so the four-level semantics are defined in exactly one
194
+ * place.
195
+ */
196
+ export declare function mergeApprovalPolicies(resolvedServers: ResolvedMcpServer[], agentOverrides: ToolApprovalOverride[], leases: ActiveLeases): Map<string, MergedToolPolicy>;
197
+ /**
198
+ * Look up whether an MCP tool requires approval.
199
+ *
200
+ * @param toolName - The actual MCP tool name (e.g., "apply_cloud_resource")
201
+ * @param mcpServerSlug - The MCP server slug (e.g., "planton")
202
+ * @param policies - The merged policy map from {@link mergeApprovalPolicies}
203
+ * @returns The policy if approval is required, undefined if auto-approved
38
204
  */
39
- export declare function mergeApprovalPolicies(resolvedServers: ResolvedMcpServer[], agentOverrides: ToolApprovalOverride[], autoApproveAll: boolean): Map<string, MergedToolPolicy>;
40
205
  export declare function lookupMcpToolPolicy(toolName: string, mcpServerSlug: string, policies: Map<string, MergedToolPolicy>): MergedToolPolicy | undefined;
41
206
  /**
42
207
  * Resolve {{args.field}} placeholders in an approval message using the
43
208
  * tool's actual arguments.
209
+ *
210
+ * Placeholder syntax matches the proto-documented format:
211
+ * - {{args.field_name}} — replaced with the argument value
212
+ * - {{tool_name}} — replaced with the tool name
213
+ * - Missing fields are replaced with "<unknown>"
44
214
  */
45
215
  export declare function resolveApprovalMessage(template: string, toolName: string, args: Record<string, unknown>): string;