@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,439 @@
1
+ /**
2
+ * Git snapshot/restore substrate for the apply-then-review HITL "capture mode".
3
+ *
4
+ * THE MODEL
5
+ * ---------
6
+ * Edits are applied to the working tree and reviewed AFTER the fact; rejecting a
7
+ * file snaps it back exactly. We use git as a NO-COMMIT snapshot/restore
8
+ * substrate at the turn boundary:
9
+ *
10
+ * 1. snapshotBaseline() at turn start — record the exact pre-turn working tree
11
+ * and pin it behind a ref so it survives a multi-day approval wait.
12
+ * 2. The agent edits files freely (the gate allows git-tracked write/edit/delete).
13
+ * 3. captureChangeSet() at turn end — diff the post-turn tree against the
14
+ * baseline into a per-file change set, and pin the post-turn ("after") tree
15
+ * behind a ref. The working tree is LEFT in its "after" state: the user
16
+ * reviews the real, applied change and the workspace browser shows it.
17
+ * 4. On resume, reconcile the working tree to the per-file decisions, sourced
18
+ * ENTIRELY from the two pinned refs (not the live tree, not the persisted
19
+ * bodies — the refs are the single source of truth):
20
+ * - approved -> applyApprovedPaths() ensures the "after" bytes.
21
+ * - rejected/undecided -> restoreToBaseline() snaps the file back to its
22
+ * exact pre-turn bytes.
23
+ * This is symmetric and idempotent: it converges to the correct end state
24
+ * regardless of the tree's current contents, so a Temporal retry or a tree
25
+ * reset is harmless.
26
+ * 5. dropCaptureRefs() releases the pinned objects.
27
+ *
28
+ * HARNESS-AGNOSTIC
29
+ * ----------------
30
+ * This is pure git plumbing keyed by `executionId`. It carries no Cursor- or
31
+ * deep-agent-specific knowledge: the runner-owned files a harness writes into the
32
+ * workspace (e.g. the Cursor gate's `.cursor/hooks.json`) are passed in as
33
+ * `excludePaths` so they never pollute the captured diff, rather than being
34
+ * hard-coded here. Both harnesses author IDENTICAL ledger entries through the
35
+ * shared producer (events.ts) on top of this substrate. A future CAS substrate
36
+ * (for ignored / non-git paths) sits beside this module.
37
+ *
38
+ * NOTHING IS PERMANENT UNTIL APPROVAL
39
+ * -----------------------------------
40
+ * Edits are visible during review, but nothing is committed and the next turn is
41
+ * blocked until the user decides; a reject snaps the file back byte-for-byte from
42
+ * the baseline ref. Shell/MCP and gitignored writes/deletes are NOT reversible by
43
+ * this substrate, so they stay on the approve-before-run gate (see each harness's
44
+ * gate: the Cursor hook and the deep-agent approval-gate middleware).
45
+ *
46
+ * WHY GIT, NO COMMITS
47
+ * -------------------
48
+ * Git is used ONLY as an exact, reversible capture/restore mechanism. We never
49
+ * move HEAD, never touch a branch, never push. Approved work stays uncommitted;
50
+ * a harness's own writeback path (if any) commits the reconciled tree afterwards.
51
+ *
52
+ * HARD INVARIANTS
53
+ * ---------------
54
+ * - NEVER `git clean -x`/`-a` or `git stash -a`: the git-excluded `.stigmer/`
55
+ * directory holds SDK resume state and MUST survive. `git clean -fd` (no `-x`)
56
+ * leaves ignored paths alone, so `.stigmer`/`lost+found` are safe.
57
+ * - Runner-owned files written into the workspace are EXCLUDED (via `excludePaths`)
58
+ * from both the baseline and the after tree, so they never pollute the captured
59
+ * diff regardless of gate-teardown ordering.
60
+ * - All staging uses a TEMP index (GIT_INDEX_FILE) so the repo's real index is
61
+ * never disturbed.
62
+ */
63
+ import { execFile } from "node:child_process";
64
+ import { mkdir, rm, writeFile } from "node:fs/promises";
65
+ import { dirname, join } from "node:path";
66
+ import { promisify } from "node:util";
67
+ import { FileChangeType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
68
+ import { bytesLookBinary } from "../file-change.js";
69
+ import { sha256Bytes } from "./digest.js";
70
+ const execFileAsync = promisify(execFile);
71
+ /** Build `:(exclude)` pathspecs for the runner-owned files a harness passes in. */
72
+ function excludePathspecs(excludePaths) {
73
+ return excludePaths.map((p) => `:(exclude)${p}`);
74
+ }
75
+ /**
76
+ * Refs that pin the per-execution baseline and after trees against GC. Exported
77
+ * so the file-review producer can stamp them onto the ledger's SnapshotRef
78
+ * (GitTreeRef.ref) without re-deriving the format. Keyed by executionId only:
79
+ * the unified gate guarantees at most one un-reconciled change set per execution
80
+ * at a time, and the reconcile drops these refs before the next turn re-pins.
81
+ */
82
+ export function baselineRef(executionId) {
83
+ return `refs/stigmer/baseline/${executionId}`;
84
+ }
85
+ export function captureRef(executionId) {
86
+ return `refs/stigmer/capture/${executionId}`;
87
+ }
88
+ /**
89
+ * A non-interactive identity for the snapshot commit objects. These commits are
90
+ * never on a branch, never pushed, and exist only to anchor a tree against
91
+ * garbage collection — but `git commit-tree` still requires an author/committer,
92
+ * and the repo may have no user.name/email configured. Supplied via env so we
93
+ * never mutate the repo's config.
94
+ */
95
+ const SNAPSHOT_IDENTITY_ENV = {
96
+ GIT_AUTHOR_NAME: "stigmer-runner",
97
+ GIT_AUTHOR_EMAIL: "runner@stigmer.local",
98
+ GIT_COMMITTER_NAME: "stigmer-runner",
99
+ GIT_COMMITTER_EMAIL: "runner@stigmer.local",
100
+ };
101
+ /**
102
+ * Run a git command in `gitRoot`. Returns stdout as a UTF-8 string. Binary
103
+ * output (file bodies) must use {@link gitBuffer} instead so bytes are exact.
104
+ */
105
+ async function git(gitRoot, args, env) {
106
+ const { stdout } = await execFileAsync("git", args, {
107
+ cwd: gitRoot,
108
+ env: env ? { ...process.env, ...env } : process.env,
109
+ maxBuffer: 256 * 1024 * 1024,
110
+ encoding: "utf-8",
111
+ });
112
+ return stdout;
113
+ }
114
+ /** Run a git command returning raw stdout BYTES (for exact file-body reads). */
115
+ async function gitBuffer(gitRoot, args) {
116
+ const { stdout } = await execFileAsync("git", args, {
117
+ cwd: gitRoot,
118
+ maxBuffer: 256 * 1024 * 1024,
119
+ encoding: "buffer",
120
+ });
121
+ return stdout;
122
+ }
123
+ /**
124
+ * Whether `dir` is inside a git work tree (the capability switch: a real git
125
+ * workspace gets capture mode, anything else keeps the deny-gate fallback).
126
+ */
127
+ export async function isGitWorkTree(dir) {
128
+ try {
129
+ const out = await git(dir, ["rev-parse", "--is-inside-work-tree"]);
130
+ return out.trim() === "true";
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
136
+ /**
137
+ * Whether a repo-relative path is capturable by this substrate — i.e. it would
138
+ * appear in the `git add -A` snapshot. A gitignored path is NOT capturable: the
139
+ * snapshot cannot see it, so it can be neither reviewed nor reverted, and a
140
+ * capture-mode gate must keep gating it. Mirrors the Cursor hook's
141
+ * `__stigmer_is_gitignored` check: `git check-ignore -q` exits 0 when the path IS
142
+ * ignored, non-zero otherwise; a non-git context / error is treated as
143
+ * not-ignored (capturable), matching the hook's allow-on-error behavior.
144
+ */
145
+ export async function isPathCapturable(gitRoot, path) {
146
+ if (!path)
147
+ return false;
148
+ try {
149
+ await git(gitRoot, ["check-ignore", "-q", "--", path]);
150
+ return false; // exit 0 -> ignored -> not capturable
151
+ }
152
+ catch {
153
+ return true; // exit 1 (not ignored) or error -> capturable
154
+ }
155
+ }
156
+ /** Whether the repo has a resolvable HEAD (false for a brand-new empty repo). */
157
+ async function headExists(gitRoot) {
158
+ try {
159
+ await git(gitRoot, ["rev-parse", "--verify", "--quiet", "HEAD"]);
160
+ return true;
161
+ }
162
+ catch {
163
+ return false;
164
+ }
165
+ }
166
+ /** Absolute path of the repo's `.git` dir (for temp index placement). */
167
+ async function resolveGitDir(gitRoot) {
168
+ const out = (await git(gitRoot, ["rev-parse", "--absolute-git-dir"])).trim();
169
+ return out;
170
+ }
171
+ /**
172
+ * Stage the entire working tree (tracked + untracked, honoring `.gitignore` /
173
+ * `.git/info/exclude`, EXCLUDING the passed runner-owned paths) into a TEMP index
174
+ * and write it out as a tree object. The real index is never touched.
175
+ *
176
+ * Using a temp index with `git add -A` records every present file as the tree's
177
+ * content; files absent from the working tree are simply absent from the tree,
178
+ * so the result is an exact snapshot of "what files exist right now and their
179
+ * bytes". `.stigmer` and other ignored paths are never staged.
180
+ */
181
+ async function writeWorkingTree(gitRoot, gitDir, label, executionId, excludePaths) {
182
+ const tmpIndex = join(gitDir, `stigmer-index-${label}-${executionId}`);
183
+ try {
184
+ await rm(tmpIndex, { force: true });
185
+ const env = { GIT_INDEX_FILE: tmpIndex };
186
+ await git(gitRoot, ["add", "-A", "--", ".", ...excludePathspecs(excludePaths)], env);
187
+ return (await git(gitRoot, ["write-tree"], env)).trim();
188
+ }
189
+ finally {
190
+ await rm(tmpIndex, { force: true });
191
+ }
192
+ }
193
+ /** Pin `tree` behind `ref` as a parent-less-or-HEAD-parented commit (anti-GC). */
194
+ async function pinTree(gitRoot, ref, tree, message) {
195
+ const args = ["commit-tree", tree, "-m", message];
196
+ if (await headExists(gitRoot)) {
197
+ args.push("-p", "HEAD");
198
+ }
199
+ const commit = (await git(gitRoot, args, SNAPSHOT_IDENTITY_ENV)).trim();
200
+ await git(gitRoot, ["update-ref", ref, commit]);
201
+ }
202
+ /**
203
+ * Snapshot the working tree at turn start and pin it behind the baseline ref.
204
+ * Returns the baseline tree sha (used by {@link captureChangeSet} and
205
+ * {@link restoreToBaseline} later in the SAME activity invocation). `excludePaths`
206
+ * are the runner-owned files the harness writes into the workspace (omit for none).
207
+ */
208
+ export async function snapshotBaseline(gitRoot, executionId, excludePaths = []) {
209
+ const gitDir = await resolveGitDir(gitRoot);
210
+ const tree = await writeWorkingTree(gitRoot, gitDir, "baseline", executionId, excludePaths);
211
+ await pinTree(gitRoot, baselineRef(executionId), tree, `stigmer baseline ${executionId}`);
212
+ return tree;
213
+ }
214
+ /**
215
+ * Capture the change set the turn produced: write the post-turn working tree,
216
+ * pin it behind the capture ref (so it survives the approval wait), and diff it
217
+ * against `baselineTree` into a per-file {@link GitSubstrateChange} list.
218
+ *
219
+ * Renames are intentionally NOT detected (`--no-renames`): a rename surfaces as
220
+ * a delete + create, which restores and applies exactly and matches the per-file
221
+ * review model.
222
+ */
223
+ export async function captureChangeSet(gitRoot, executionId, baselineTree, excludePaths = []) {
224
+ const gitDir = await resolveGitDir(gitRoot);
225
+ const afterTree = await writeWorkingTree(gitRoot, gitDir, "capture", executionId, excludePaths);
226
+ await pinTree(gitRoot, captureRef(executionId), afterTree, `stigmer capture ${executionId}`);
227
+ const raw = await git(gitRoot, [
228
+ "diff",
229
+ "--no-renames",
230
+ "--name-status",
231
+ "-z",
232
+ baselineTree,
233
+ afterTree,
234
+ ]);
235
+ const changes = [];
236
+ for (const { status, path } of parseNameStatusZ(raw)) {
237
+ const change = await buildCapturedChange(gitRoot, baselineTree, afterTree, status, path);
238
+ if (change)
239
+ changes.push(change);
240
+ }
241
+ return { baselineTree, afterTree, changes };
242
+ }
243
+ /**
244
+ * Restore the given files to their `baselineTree` (pre-turn) bytes. On resume
245
+ * this reverts the REJECTED/undecided subset so a discarded change snaps back
246
+ * exactly; it is the generic "ensure baseline bytes" primitive. Surgical
247
+ * (bounded by the passed change set): an agent-created file is removed; an
248
+ * agent-modified or agent-deleted file is rewritten with its baseline bytes.
249
+ * `.stigmer` and other ignored paths are never touched (they are not in the
250
+ * change set). Idempotent — safe to re-run (e.g. on a Temporal retry).
251
+ */
252
+ export async function restoreToBaseline(gitRoot, baselineTree, changes) {
253
+ for (const change of changes) {
254
+ const abs = join(gitRoot, change.path);
255
+ if (change.changeType === FileChangeType.CREATE) {
256
+ await rm(abs, { force: true });
257
+ }
258
+ else {
259
+ // MODIFY or DELETE: the baseline holds the file — restore its exact bytes.
260
+ await writeBlobToDisk(gitRoot, baselineTree, change.path, abs);
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Ensure the APPROVED files hold their captured "after" bytes, as uncommitted
266
+ * working-tree changes (no commit). In capture mode the agent's edits are left
267
+ * applied through the review window, so on resume this is normally an idempotent
268
+ * re-assert of bytes already on disk; sourcing from the pinned "after" tree also
269
+ * makes it self-healing if the tree was reset (Temporal retry / sandbox
270
+ * recycle). An approved CREATE/MODIFY writes the after bytes; an approved DELETE
271
+ * removes the file. Rejected/undecided paths are not passed in (they go to
272
+ * {@link restoreToBaseline}).
273
+ */
274
+ export async function applyApprovedPaths(gitRoot, afterTree, approved) {
275
+ for (const change of approved) {
276
+ const abs = join(gitRoot, change.path);
277
+ if (change.changeType === FileChangeType.DELETE) {
278
+ await rm(abs, { force: true });
279
+ }
280
+ else {
281
+ // CREATE or MODIFY: write the agent's approved bytes from the after tree.
282
+ await writeBlobToDisk(gitRoot, afterTree, change.path, abs);
283
+ }
284
+ }
285
+ }
286
+ /**
287
+ * Recompute the captured change set on a RESUME, from the pinned baseline and
288
+ * capture refs — the authoritative source that survived the approval wait,
289
+ * independent of any persisted fidelity. Returns `undefined` when this was not a
290
+ * capture turn (the capture ref is absent), so the caller can fall through to the
291
+ * non-capture path.
292
+ */
293
+ export async function recomputeChangeSet(gitRoot, executionId) {
294
+ const baselineTree = await resolveRefTree(gitRoot, baselineRef(executionId));
295
+ const afterTree = await resolveRefTree(gitRoot, captureRef(executionId));
296
+ if (!baselineTree || !afterTree)
297
+ return undefined;
298
+ const raw = await git(gitRoot, [
299
+ "diff",
300
+ "--no-renames",
301
+ "--name-status",
302
+ "-z",
303
+ baselineTree,
304
+ afterTree,
305
+ ]);
306
+ const changes = [];
307
+ for (const { status, path } of parseNameStatusZ(raw)) {
308
+ const change = await buildCapturedChange(gitRoot, baselineTree, afterTree, status, path);
309
+ if (change)
310
+ changes.push(change);
311
+ }
312
+ return { baselineTree, afterTree, changes };
313
+ }
314
+ /** Resolve a ref to its tree sha, or `undefined` when the ref does not exist. */
315
+ async function resolveRefTree(gitRoot, ref) {
316
+ try {
317
+ return (await git(gitRoot, ["rev-parse", "--verify", "--quiet", `${ref}^{tree}`])).trim();
318
+ }
319
+ catch {
320
+ return undefined;
321
+ }
322
+ }
323
+ /** The ref pinning the post-reconcile (approved) tree for the RECONCILED event. */
324
+ function approvedRef(executionId) {
325
+ return `refs/stigmer/approved/${executionId}`;
326
+ }
327
+ /**
328
+ * Snapshot the post-reconcile working tree (after approved bytes were applied and
329
+ * rejected files were reverted) and pin it behind the approved ref. Returns the
330
+ * approved tree sha for the RECONCILED event's `approved_snapshot`, plus the ref
331
+ * so the producer can stamp the SnapshotRef. Idempotent under a Temporal retry.
332
+ */
333
+ export async function snapshotApproved(gitRoot, executionId, excludePaths = []) {
334
+ const gitDir = await resolveGitDir(gitRoot);
335
+ const tree = await writeWorkingTree(gitRoot, gitDir, "approved", executionId, excludePaths);
336
+ const ref = approvedRef(executionId);
337
+ await pinTree(gitRoot, ref, tree, `stigmer approved ${executionId}`);
338
+ return { treeOid: tree, ref };
339
+ }
340
+ /** Release the per-execution baseline, capture, and approved refs (idempotent). */
341
+ export async function dropCaptureRefs(gitRoot, executionId) {
342
+ for (const ref of [baselineRef(executionId), captureRef(executionId), approvedRef(executionId)]) {
343
+ try {
344
+ await git(gitRoot, ["update-ref", "-d", ref]);
345
+ }
346
+ catch {
347
+ // Already gone — nothing to release.
348
+ }
349
+ }
350
+ }
351
+ /**
352
+ * Parse `git diff --name-status -z` output: a flat NUL-delimited stream of
353
+ * `STATUS\0PATH\0` pairs. NUL-delimiting avoids every quoting/escaping concern
354
+ * for paths with spaces, quotes, or unicode.
355
+ */
356
+ function parseNameStatusZ(raw) {
357
+ const parts = raw.split("\u0000");
358
+ const entries = [];
359
+ for (let i = 0; i + 1 < parts.length; i += 2) {
360
+ const status = parts[i];
361
+ const path = parts[i + 1];
362
+ if (!status || !path)
363
+ continue;
364
+ entries.push({ status: status[0], path });
365
+ }
366
+ return entries;
367
+ }
368
+ /** Read a blob's exact BYTES from a tree, or `undefined` when absent. */
369
+ async function readBlobBytes(gitRoot, tree, path) {
370
+ try {
371
+ return await gitBuffer(gitRoot, ["cat-file", "-p", `${tree}:${path}`]);
372
+ }
373
+ catch {
374
+ return undefined;
375
+ }
376
+ }
377
+ /**
378
+ * Read one side of a change as {@link CapturedContent}, computing its identity
379
+ * from the RAW bytes (never a lossy UTF-8 decode): a binary blob carries only its
380
+ * byte-true content address (no body — it reconciles from the git ref), while a
381
+ * text blob is carried inline. Returns `undefined` only when the blob is absent
382
+ * from the tree (the side does not exist for this changeType).
383
+ */
384
+ async function readSide(gitRoot, tree, path) {
385
+ const bytes = await readBlobBytes(gitRoot, tree, path);
386
+ if (bytes === undefined)
387
+ return undefined;
388
+ // Identity is always computed over the RAW bytes at the source — never a lossy
389
+ // UTF-8 re-encode — so the enforcement digest is byte-true for binary and text
390
+ // alike. A binary blob carries no body (it reconciles from the git ref); a text
391
+ // blob carries its inline body for the review diff.
392
+ const sha256 = sha256Bytes(bytes);
393
+ if (bytesLookBinary(bytes)) {
394
+ return { kind: "binary", sha256 };
395
+ }
396
+ return { kind: "inline", text: bytes.toString("utf8"), sha256 };
397
+ }
398
+ /** Write a blob's exact bytes from a tree to `abs` (creating parent dirs). */
399
+ async function writeBlobToDisk(gitRoot, tree, path, abs) {
400
+ const buf = await gitBuffer(gitRoot, ["cat-file", "-p", `${tree}:${path}`]);
401
+ await mkdir(dirname(abs), { recursive: true });
402
+ await writeFile(abs, buf);
403
+ }
404
+ /** An empty inline side — the default when a MODIFY blob is unexpectedly absent. */
405
+ const EMPTY_INLINE = { kind: "inline", text: "" };
406
+ /**
407
+ * Build a {@link GitSubstrateChange} from a diff entry. WHOLE_FILE capture: the
408
+ * before/after content comes from the two trees, with identity computed over the
409
+ * exact bytes git holds (see {@link readSide}) — so the review shows the file's
410
+ * true net change and the enforcement digest is byte-true, binary or text alike.
411
+ * A binary side is carried as a content address only (no body); large text bodies
412
+ * are offloaded later at the persist chokepoint.
413
+ */
414
+ async function buildCapturedChange(gitRoot, baselineTree, afterTree, status, path) {
415
+ if (status === "A") {
416
+ const after = await readSide(gitRoot, afterTree, path);
417
+ if (after === undefined)
418
+ return undefined;
419
+ return { path, changeType: FileChangeType.CREATE, after };
420
+ }
421
+ if (status === "D") {
422
+ const before = await readSide(gitRoot, baselineTree, path);
423
+ if (before === undefined)
424
+ return undefined;
425
+ return { path, changeType: FileChangeType.DELETE, before };
426
+ }
427
+ // Modified (M) — and any other status (T type-change, etc.) treated as MODIFY.
428
+ const before = await readSide(gitRoot, baselineTree, path);
429
+ const after = await readSide(gitRoot, afterTree, path);
430
+ if (before === undefined && after === undefined)
431
+ return undefined;
432
+ return {
433
+ path,
434
+ changeType: FileChangeType.MODIFY,
435
+ before: before ?? EMPTY_INLINE,
436
+ after: after ?? EMPTY_INLINE,
437
+ };
438
+ }
439
+ //# sourceMappingURL=git-substrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-substrate.js","sourceRoot":"","sources":["../../../src/shared/filereview/git-substrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The runner's file-review producer: harness-agnostic digest + event authoring
3
+ * for the apply-then-review HITL subsystem. Consumed by both the Cursor and
4
+ * deep-agent harnesses to author identical ledger entries.
5
+ */
6
+ export { aggregateDigest, fileChangeKindName, fileDigest, sha256Bytes, sha256Hex, type FileDigestInput, } from "./digest.js";
7
+ export { appendFileReviewEvents, buildBaselineCapturedEvent, buildCandidateCapturedEvent, buildCapturedFileChange, buildFailedEvent, buildReconciledEvent, eventId, hasCandidateCaptured, type CapturedChangeInput, type ChangeSetContext, } from "./events.js";
8
+ export { applyCaptureDecisions, captureBaselineToLedger, captureCandidateToLedger, type CaptureResumeResult, } from "./capture.js";
9
+ export { isGitWorkTree } from "./git-substrate.js";
10
+ export { applyCasApproved, casBlobKey, casBlobReader, casManifestKey, loadCasManifest, restoreCasToBaseline, snapshotCasChangeSet, type BlobReader, type CasBlobRef, type CasCapturedFile, type CasManifest, type CasPathCapture, type CasSnapshotRef, } from "./cas-substrate.js";
11
+ export { isSecretLikePath, partitionIgnoredPathsBySecret, SECRET_BASENAME_PATTERNS, SECRET_PATH_PATTERNS, type CasSecretPartition, } from "./secret-paths.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The runner's file-review producer: harness-agnostic digest + event authoring
3
+ * for the apply-then-review HITL subsystem. Consumed by both the Cursor and
4
+ * deep-agent harnesses to author identical ledger entries.
5
+ */
6
+ export { aggregateDigest, fileChangeKindName, fileDigest, sha256Bytes, sha256Hex, } from "./digest.js";
7
+ export { appendFileReviewEvents, buildBaselineCapturedEvent, buildCandidateCapturedEvent, buildCapturedFileChange, buildFailedEvent, buildReconciledEvent, eventId, hasCandidateCaptured, } from "./events.js";
8
+ export { applyCaptureDecisions, captureBaselineToLedger, captureCandidateToLedger, } from "./capture.js";
9
+ export { isGitWorkTree } from "./git-substrate.js";
10
+ export { applyCasApproved, casBlobKey, casBlobReader, casManifestKey, loadCasManifest, restoreCasToBaseline, snapshotCasChangeSet, } from "./cas-substrate.js";
11
+ export { isSecretLikePath, partitionIgnoredPathsBySecret, SECRET_BASENAME_PATTERNS, SECRET_PATH_PATTERNS, } from "./secret-paths.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/filereview/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,SAAS,GAEV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,EACpB,OAAO,EACP,oBAAoB,GAGrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,GAEzB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,oBAAoB,GAOrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,gBAAgB,EAChB,6BAA6B,EAC7B,wBAAwB,EACxB,oBAAoB,GAErB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The secret-safety gate for CAS capture (design doc 12).
3
+ *
4
+ * The git substrate never captures gitignored paths, which was an accidental
5
+ * safety property: `.gitignore` is where projects keep secrets (`.env`, private
6
+ * keys, credentials). The CAS substrate's whole purpose is to start capturing
7
+ * ignored / non-git paths — so, done naively, it would write secret bytes into
8
+ * durable artifact storage. This module is the fail-closed gate that prevents
9
+ * that: a path classified secret-like is BLOCKED from capture (authored as
10
+ * DIFF_UNREVIEWABLE instead) and its bytes never leave the workspace.
11
+ *
12
+ * Scope discipline (design doc 12 D2): this is deliberately a small, explicit,
13
+ * deterministic matcher — NOT the Phase-4 `sensitivity` taxonomy, NOT ML. It is
14
+ * a pure function over the path, so the cross-edition corpus can lock it (a path
15
+ * either blocks or captures, identically everywhere). The matcher errs toward
16
+ * blocking: a path only needs to LOOK secret-like to be withheld, because the
17
+ * cost of withholding a non-secret (it stays on the deny-gate, as today) is far
18
+ * lower than the cost of persisting a real secret.
19
+ *
20
+ * @since File-Change HITL Redesign (Phase 3 — CAS / DD-E)
21
+ */
22
+ /**
23
+ * Basename patterns that mark a file secret-like. Matched case-insensitively
24
+ * against the final path segment. Kept as an explicit, reviewable list — adding
25
+ * a pattern is a deliberate, corpus-locked change, never a heuristic guess.
26
+ */
27
+ export declare const SECRET_BASENAME_PATTERNS: readonly RegExp[];
28
+ /**
29
+ * Path-fragment patterns that mark a file secret-like by WHERE it lives, matched
30
+ * against the normalized (forward-slash) full path. Covers credential stores
31
+ * whose basenames alone are ambiguous.
32
+ */
33
+ export declare const SECRET_PATH_PATTERNS: readonly RegExp[];
34
+ /**
35
+ * Whether a path is secret-like and must NOT be captured into the durable CAS
36
+ * store. Fail-closed: an empty/unknown path is treated as secret-like (withheld)
37
+ * rather than captured.
38
+ */
39
+ export declare function isSecretLikePath(path: string): boolean;
40
+ /** How the turn's observed gitignored paths split under the secret gate. */
41
+ export interface CasSecretPartition {
42
+ /** Paths safe to capture into durable CAS (their bytes may be persisted). */
43
+ readonly capturablePaths: readonly string[];
44
+ /**
45
+ * Paths withheld from capture — authored as content-less DIFF_UNREVIEWABLE.
46
+ * The union of the gate's up-front blocks and any observed secret-like path.
47
+ */
48
+ readonly unreviewablePaths: readonly string[];
49
+ }
50
+ /**
51
+ * Split a turn's observed gitignored paths into capturable vs withheld — the
52
+ * single source of truth for "which ignored bytes may reach durable storage".
53
+ *
54
+ * `unreviewablePaths = gateBlockedPaths ∪ { p ∈ observed : isSecretLikePath(p) }`
55
+ * and `capturablePaths = { p ∈ observed : ¬isSecretLikePath(p) }`. The
56
+ * `isSecretLikePath` re-check over `observed` is the fail-closed backstop that
57
+ * holds **even under the global bypass** (`spec.auto_approve_all`): there the
58
+ * approval gate is not installed, so `gateBlockedPaths` is empty and this
59
+ * re-check is the only thing keeping a secret's bytes out of CAS. Order is
60
+ * preserved (gate blocks first, then observed order) and duplicates are folded,
61
+ * so the result is deterministic for the cross-edition corpus.
62
+ */
63
+ export declare function partitionIgnoredPathsBySecret(observedPaths: Iterable<string>, gateBlockedPaths: ReadonlySet<string>): CasSecretPartition;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The secret-safety gate for CAS capture (design doc 12).
3
+ *
4
+ * The git substrate never captures gitignored paths, which was an accidental
5
+ * safety property: `.gitignore` is where projects keep secrets (`.env`, private
6
+ * keys, credentials). The CAS substrate's whole purpose is to start capturing
7
+ * ignored / non-git paths — so, done naively, it would write secret bytes into
8
+ * durable artifact storage. This module is the fail-closed gate that prevents
9
+ * that: a path classified secret-like is BLOCKED from capture (authored as
10
+ * DIFF_UNREVIEWABLE instead) and its bytes never leave the workspace.
11
+ *
12
+ * Scope discipline (design doc 12 D2): this is deliberately a small, explicit,
13
+ * deterministic matcher — NOT the Phase-4 `sensitivity` taxonomy, NOT ML. It is
14
+ * a pure function over the path, so the cross-edition corpus can lock it (a path
15
+ * either blocks or captures, identically everywhere). The matcher errs toward
16
+ * blocking: a path only needs to LOOK secret-like to be withheld, because the
17
+ * cost of withholding a non-secret (it stays on the deny-gate, as today) is far
18
+ * lower than the cost of persisting a real secret.
19
+ *
20
+ * @since File-Change HITL Redesign (Phase 3 — CAS / DD-E)
21
+ */
22
+ /**
23
+ * Basename patterns that mark a file secret-like. Matched case-insensitively
24
+ * against the final path segment. Kept as an explicit, reviewable list — adding
25
+ * a pattern is a deliberate, corpus-locked change, never a heuristic guess.
26
+ */
27
+ export const SECRET_BASENAME_PATTERNS = [
28
+ /^\.env(\..+)?$/, // .env, .env.local, .env.production, ...
29
+ /^\.npmrc$/,
30
+ /^\.netrc$/,
31
+ /^\.pgpass$/,
32
+ /^\.htpasswd$/,
33
+ /^credentials(\.[A-Za-z0-9]+)?$/, // credentials, credentials.json, ...
34
+ /^secrets?(\.[A-Za-z0-9]+)?$/, // secret / secrets / secrets.yaml, ...
35
+ /^id_(rsa|dsa|ecdsa|ed25519)$/, // private SSH keys (no .pub)
36
+ /.*\.(pem|key|pfx|p12|keystore|jks|asc|ppk)$/,
37
+ /.*\.tfstate(\.backup)?$/, // terraform state embeds secrets
38
+ /.*\.tfvars$/,
39
+ /.*\.(kdbx)$/, // password databases
40
+ ];
41
+ /**
42
+ * Path-fragment patterns that mark a file secret-like by WHERE it lives, matched
43
+ * against the normalized (forward-slash) full path. Covers credential stores
44
+ * whose basenames alone are ambiguous.
45
+ */
46
+ export const SECRET_PATH_PATTERNS = [
47
+ /(^|\/)\.ssh\//, // ~/.ssh/* and repo-local .ssh/*
48
+ /(^|\/)\.aws\/credentials$/,
49
+ /(^|\/)\.gnupg\//,
50
+ /(^|\/)\.docker\/config\.json$/,
51
+ /(^|\/)\.kube\/config$/,
52
+ ];
53
+ /** The final path segment (basename), for both `/` and `\` separators. */
54
+ function basename(path) {
55
+ const normalized = path.replace(/\\/g, "/");
56
+ const idx = normalized.lastIndexOf("/");
57
+ return idx >= 0 ? normalized.slice(idx + 1) : normalized;
58
+ }
59
+ /**
60
+ * Whether a path is secret-like and must NOT be captured into the durable CAS
61
+ * store. Fail-closed: an empty/unknown path is treated as secret-like (withheld)
62
+ * rather than captured.
63
+ */
64
+ export function isSecretLikePath(path) {
65
+ if (!path)
66
+ return true;
67
+ const normalized = path.replace(/\\/g, "/");
68
+ const base = basename(normalized).toLowerCase();
69
+ for (const re of SECRET_BASENAME_PATTERNS) {
70
+ if (re.test(base))
71
+ return true;
72
+ }
73
+ const lowerPath = normalized.toLowerCase();
74
+ for (const re of SECRET_PATH_PATTERNS) {
75
+ if (re.test(lowerPath))
76
+ return true;
77
+ }
78
+ return false;
79
+ }
80
+ /**
81
+ * Split a turn's observed gitignored paths into capturable vs withheld — the
82
+ * single source of truth for "which ignored bytes may reach durable storage".
83
+ *
84
+ * `unreviewablePaths = gateBlockedPaths ∪ { p ∈ observed : isSecretLikePath(p) }`
85
+ * and `capturablePaths = { p ∈ observed : ¬isSecretLikePath(p) }`. The
86
+ * `isSecretLikePath` re-check over `observed` is the fail-closed backstop that
87
+ * holds **even under the global bypass** (`spec.auto_approve_all`): there the
88
+ * approval gate is not installed, so `gateBlockedPaths` is empty and this
89
+ * re-check is the only thing keeping a secret's bytes out of CAS. Order is
90
+ * preserved (gate blocks first, then observed order) and duplicates are folded,
91
+ * so the result is deterministic for the cross-edition corpus.
92
+ */
93
+ export function partitionIgnoredPathsBySecret(observedPaths, gateBlockedPaths) {
94
+ const unreviewable = new Set(gateBlockedPaths);
95
+ const capturablePaths = [];
96
+ for (const path of observedPaths) {
97
+ if (isSecretLikePath(path)) {
98
+ unreviewable.add(path);
99
+ continue;
100
+ }
101
+ capturablePaths.push(path);
102
+ }
103
+ return { capturablePaths, unreviewablePaths: [...unreviewable] };
104
+ }
105
+ //# sourceMappingURL=secret-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-paths.js","sourceRoot":"","sources":["../../../src/shared/filereview/secret-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,gBAAgB,EAAE,yCAAyC;IAC3D,WAAW;IACX,WAAW;IACX,YAAY;IACZ,cAAc;IACd,gCAAgC,EAAE,qCAAqC;IACvE,6BAA6B,EAAE,uCAAuC;IACtE,8BAA8B,EAAE,6BAA6B;IAC7D,6CAA6C;IAC7C,yBAAyB,EAAE,iCAAiC;IAC5D,aAAa;IACb,aAAa,EAAE,qBAAqB;CACrC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,eAAe,EAAE,iCAAiC;IAClD,2BAA2B;IAC3B,iBAAiB;IACjB,+BAA+B;IAC/B,uBAAuB;CACxB,CAAC;AAEF,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IAEhD,KAAK,MAAM,EAAE,IAAI,wBAAwB,EAAE,CAAC;QAC1C,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IACD,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAC3C,KAAK,MAAM,EAAE,IAAI,oBAAoB,EAAE,CAAC;QACtC,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAaD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,6BAA6B,CAC3C,aAA+B,EAC/B,gBAAqC;IAErC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,gBAAgB,CAAC,CAAC;IACvD,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvB,SAAS;QACX,CAAC;QACD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC;AACnE,CAAC"}