@smthrs/std 0.0.0-stage → 1.0.0-rc.4

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 (555) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/LICENSE +21 -0
  3. package/README.md +152 -2
  4. package/dist/cjs/ApplyPatch.d.ts +174 -0
  5. package/dist/cjs/ApplyPatch.d.ts.map +1 -0
  6. package/dist/cjs/ApplyPatch.js +309 -0
  7. package/dist/cjs/ApplyPatch.js.map +7 -0
  8. package/dist/cjs/Bash.d.ts +380 -0
  9. package/dist/cjs/Bash.d.ts.map +1 -0
  10. package/dist/cjs/Bash.js +332 -0
  11. package/dist/cjs/Bash.js.map +7 -0
  12. package/dist/cjs/Checkpoints.d.ts +279 -0
  13. package/dist/cjs/Checkpoints.d.ts.map +1 -0
  14. package/dist/cjs/Checkpoints.js +145 -0
  15. package/dist/cjs/Checkpoints.js.map +7 -0
  16. package/dist/cjs/Container.d.ts +132 -0
  17. package/dist/cjs/Container.d.ts.map +1 -0
  18. package/dist/cjs/Container.js +113 -0
  19. package/dist/cjs/Container.js.map +7 -0
  20. package/dist/cjs/Edit.d.ts +203 -0
  21. package/dist/cjs/Edit.d.ts.map +1 -0
  22. package/dist/cjs/Edit.js +258 -0
  23. package/dist/cjs/Edit.js.map +7 -0
  24. package/dist/cjs/ExaWebSearch.d.ts +22 -0
  25. package/dist/cjs/ExaWebSearch.d.ts.map +1 -0
  26. package/dist/cjs/ExaWebSearch.js +138 -0
  27. package/dist/cjs/ExaWebSearch.js.map +7 -0
  28. package/dist/cjs/Explore.d.ts +328 -0
  29. package/dist/cjs/Explore.d.ts.map +1 -0
  30. package/dist/cjs/Explore.js +90 -0
  31. package/dist/cjs/Explore.js.map +7 -0
  32. package/dist/cjs/Fetch.d.ts +130 -0
  33. package/dist/cjs/Fetch.d.ts.map +1 -0
  34. package/dist/cjs/Fetch.js +64 -0
  35. package/dist/cjs/Fetch.js.map +7 -0
  36. package/dist/cjs/Glob.d.ts +204 -0
  37. package/dist/cjs/Glob.d.ts.map +1 -0
  38. package/dist/cjs/Glob.js +94 -0
  39. package/dist/cjs/Glob.js.map +7 -0
  40. package/dist/cjs/Grep.d.ts +347 -0
  41. package/dist/cjs/Grep.d.ts.map +1 -0
  42. package/dist/cjs/Grep.js +181 -0
  43. package/dist/cjs/Grep.js.map +7 -0
  44. package/dist/cjs/HttpPost.d.ts +130 -0
  45. package/dist/cjs/HttpPost.d.ts.map +1 -0
  46. package/dist/cjs/HttpPost.js +72 -0
  47. package/dist/cjs/HttpPost.js.map +7 -0
  48. package/dist/cjs/LanguageServer.d.ts +90 -0
  49. package/dist/cjs/LanguageServer.d.ts.map +1 -0
  50. package/dist/cjs/LanguageServer.js +60 -0
  51. package/dist/cjs/LanguageServer.js.map +7 -0
  52. package/dist/cjs/Ls.d.ts +164 -0
  53. package/dist/cjs/Ls.d.ts.map +1 -0
  54. package/dist/cjs/Ls.js +136 -0
  55. package/dist/cjs/Ls.js.map +7 -0
  56. package/dist/cjs/Lsp.d.ts +125 -0
  57. package/dist/cjs/Lsp.d.ts.map +1 -0
  58. package/dist/cjs/Lsp.js +137 -0
  59. package/dist/cjs/Lsp.js.map +7 -0
  60. package/dist/cjs/Manifest.d.ts +918 -0
  61. package/dist/cjs/Manifest.d.ts.map +1 -0
  62. package/dist/cjs/Manifest.js +144 -0
  63. package/dist/cjs/Manifest.js.map +7 -0
  64. package/dist/cjs/NativeSearch.d.ts +38 -0
  65. package/dist/cjs/NativeSearch.d.ts.map +1 -0
  66. package/dist/cjs/NativeSearch.js +326 -0
  67. package/dist/cjs/NativeSearch.js.map +7 -0
  68. package/dist/cjs/NodeLanguageServer.d.ts +128 -0
  69. package/dist/cjs/NodeLanguageServer.d.ts.map +1 -0
  70. package/dist/cjs/NodeLanguageServer.js +796 -0
  71. package/dist/cjs/NodeLanguageServer.js.map +7 -0
  72. package/dist/cjs/PortableSearch.d.ts +24 -0
  73. package/dist/cjs/PortableSearch.d.ts.map +1 -0
  74. package/dist/cjs/PortableSearch.js +233 -0
  75. package/dist/cjs/PortableSearch.js.map +7 -0
  76. package/dist/cjs/Probe.d.ts +193 -0
  77. package/dist/cjs/Probe.d.ts.map +1 -0
  78. package/dist/cjs/Probe.js +134 -0
  79. package/dist/cjs/Probe.js.map +7 -0
  80. package/dist/cjs/Read.d.ts +189 -0
  81. package/dist/cjs/Read.d.ts.map +1 -0
  82. package/dist/cjs/Read.js +223 -0
  83. package/dist/cjs/Read.js.map +7 -0
  84. package/dist/cjs/Relocate.d.ts +73 -0
  85. package/dist/cjs/Relocate.d.ts.map +1 -0
  86. package/dist/cjs/Relocate.js +72 -0
  87. package/dist/cjs/Relocate.js.map +7 -0
  88. package/dist/cjs/Search.d.ts +163 -0
  89. package/dist/cjs/Search.d.ts.map +1 -0
  90. package/dist/cjs/Search.js +51 -0
  91. package/dist/cjs/Search.js.map +7 -0
  92. package/dist/cjs/SearchConformance.d.ts +115 -0
  93. package/dist/cjs/SearchConformance.d.ts.map +1 -0
  94. package/dist/cjs/SearchConformance.js +172 -0
  95. package/dist/cjs/SearchConformance.js.map +7 -0
  96. package/dist/cjs/SearchContract.d.ts +114 -0
  97. package/dist/cjs/SearchContract.d.ts.map +1 -0
  98. package/dist/cjs/SearchContract.js +339 -0
  99. package/dist/cjs/SearchContract.js.map +7 -0
  100. package/dist/cjs/ShellCommand.d.ts +164 -0
  101. package/dist/cjs/ShellCommand.d.ts.map +1 -0
  102. package/dist/cjs/ShellCommand.js +102 -0
  103. package/dist/cjs/ShellCommand.js.map +7 -0
  104. package/dist/cjs/StdError.d.ts +55 -0
  105. package/dist/cjs/StdError.d.ts.map +1 -0
  106. package/dist/cjs/StdError.js +74 -0
  107. package/dist/cjs/StdError.js.map +7 -0
  108. package/dist/cjs/TestRun.d.ts +311 -0
  109. package/dist/cjs/TestRun.d.ts.map +1 -0
  110. package/dist/cjs/TestRun.js +228 -0
  111. package/dist/cjs/TestRun.js.map +7 -0
  112. package/dist/cjs/TestRunner.d.ts +102 -0
  113. package/dist/cjs/TestRunner.d.ts.map +1 -0
  114. package/dist/cjs/TestRunner.js +54 -0
  115. package/dist/cjs/TestRunner.js.map +7 -0
  116. package/dist/cjs/TreeFingerprint.d.ts +140 -0
  117. package/dist/cjs/TreeFingerprint.d.ts.map +1 -0
  118. package/dist/cjs/TreeFingerprint.js +87 -0
  119. package/dist/cjs/TreeFingerprint.js.map +7 -0
  120. package/dist/cjs/UpdatePlan.d.ts +152 -0
  121. package/dist/cjs/UpdatePlan.d.ts.map +1 -0
  122. package/dist/cjs/UpdatePlan.js +87 -0
  123. package/dist/cjs/UpdatePlan.js.map +7 -0
  124. package/dist/cjs/WebFetch.d.ts +134 -0
  125. package/dist/cjs/WebFetch.d.ts.map +1 -0
  126. package/dist/cjs/WebFetch.js +140 -0
  127. package/dist/cjs/WebFetch.js.map +7 -0
  128. package/dist/cjs/WebSearch.d.ts +181 -0
  129. package/dist/cjs/WebSearch.d.ts.map +1 -0
  130. package/dist/cjs/WebSearch.js +86 -0
  131. package/dist/cjs/WebSearch.js.map +7 -0
  132. package/dist/cjs/Write.d.ts +147 -0
  133. package/dist/cjs/Write.d.ts.map +1 -0
  134. package/dist/cjs/Write.js +122 -0
  135. package/dist/cjs/Write.js.map +7 -0
  136. package/dist/cjs/index.d.ts +127 -0
  137. package/dist/cjs/index.d.ts.map +1 -0
  138. package/dist/cjs/index.js +99 -0
  139. package/dist/cjs/index.js.map +7 -0
  140. package/dist/cjs/internal/ApplyPatch.d.ts +145 -0
  141. package/dist/cjs/internal/ApplyPatch.d.ts.map +1 -0
  142. package/dist/cjs/internal/ApplyPatch.js +462 -0
  143. package/dist/cjs/internal/ApplyPatch.js.map +7 -0
  144. package/dist/cjs/internal/CodexText.d.ts +73 -0
  145. package/dist/cjs/internal/CodexText.d.ts.map +1 -0
  146. package/dist/cjs/internal/CodexText.js +108 -0
  147. package/dist/cjs/internal/CodexText.js.map +7 -0
  148. package/dist/cjs/internal/Declaration.d.ts +49 -0
  149. package/dist/cjs/internal/Declaration.d.ts.map +1 -0
  150. package/dist/cjs/internal/Declaration.js +46 -0
  151. package/dist/cjs/internal/Declaration.js.map +7 -0
  152. package/dist/cjs/internal/Diagnostics.d.ts +77 -0
  153. package/dist/cjs/internal/Diagnostics.d.ts.map +1 -0
  154. package/dist/cjs/internal/Diagnostics.js +89 -0
  155. package/dist/cjs/internal/Diagnostics.js.map +7 -0
  156. package/dist/cjs/internal/EnvelopePrecheck.d.ts +67 -0
  157. package/dist/cjs/internal/EnvelopePrecheck.d.ts.map +1 -0
  158. package/dist/cjs/internal/EnvelopePrecheck.js +124 -0
  159. package/dist/cjs/internal/EnvelopePrecheck.js.map +7 -0
  160. package/dist/cjs/internal/Exec.d.ts +139 -0
  161. package/dist/cjs/internal/Exec.d.ts.map +1 -0
  162. package/dist/cjs/internal/Exec.js +158 -0
  163. package/dist/cjs/internal/Exec.js.map +7 -0
  164. package/dist/cjs/internal/FileMutation.d.ts +109 -0
  165. package/dist/cjs/internal/FileMutation.d.ts.map +1 -0
  166. package/dist/cjs/internal/FileMutation.js +116 -0
  167. package/dist/cjs/internal/FileMutation.js.map +7 -0
  168. package/dist/cjs/internal/FsFailure.d.ts +38 -0
  169. package/dist/cjs/internal/FsFailure.d.ts.map +1 -0
  170. package/dist/cjs/internal/FsFailure.js +40 -0
  171. package/dist/cjs/internal/FsFailure.js.map +7 -0
  172. package/dist/cjs/internal/GitWorktree.d.ts +108 -0
  173. package/dist/cjs/internal/GitWorktree.d.ts.map +1 -0
  174. package/dist/cjs/internal/GitWorktree.js +276 -0
  175. package/dist/cjs/internal/GitWorktree.js.map +7 -0
  176. package/dist/cjs/internal/Grouping.d.ts +51 -0
  177. package/dist/cjs/internal/Grouping.d.ts.map +1 -0
  178. package/dist/cjs/internal/Grouping.js +83 -0
  179. package/dist/cjs/internal/Grouping.js.map +7 -0
  180. package/dist/cjs/internal/Html.d.ts +20 -0
  181. package/dist/cjs/internal/Html.d.ts.map +1 -0
  182. package/dist/cjs/internal/Html.js +81 -0
  183. package/dist/cjs/internal/Html.js.map +7 -0
  184. package/dist/cjs/internal/Http.d.ts +95 -0
  185. package/dist/cjs/internal/Http.d.ts.map +1 -0
  186. package/dist/cjs/internal/Http.js +153 -0
  187. package/dist/cjs/internal/Http.js.map +7 -0
  188. package/dist/cjs/internal/HttpNetwork.d.ts +27 -0
  189. package/dist/cjs/internal/HttpNetwork.d.ts.map +1 -0
  190. package/dist/cjs/internal/HttpNetwork.js +146 -0
  191. package/dist/cjs/internal/HttpNetwork.js.map +7 -0
  192. package/dist/cjs/internal/Ignore.d.ts +37 -0
  193. package/dist/cjs/internal/Ignore.d.ts.map +1 -0
  194. package/dist/cjs/internal/Ignore.js +100 -0
  195. package/dist/cjs/internal/Ignore.js.map +7 -0
  196. package/dist/cjs/internal/LinearRegex.d.ts +19 -0
  197. package/dist/cjs/internal/LinearRegex.d.ts.map +1 -0
  198. package/dist/cjs/internal/LinearRegex.js +166 -0
  199. package/dist/cjs/internal/LinearRegex.js.map +7 -0
  200. package/dist/cjs/internal/Match.d.ts +85 -0
  201. package/dist/cjs/internal/Match.d.ts.map +1 -0
  202. package/dist/cjs/internal/Match.js +99 -0
  203. package/dist/cjs/internal/Match.js.map +7 -0
  204. package/dist/cjs/internal/Paths.d.ts +23 -0
  205. package/dist/cjs/internal/Paths.d.ts.map +1 -0
  206. package/dist/cjs/internal/Paths.js +52 -0
  207. package/dist/cjs/internal/Paths.js.map +7 -0
  208. package/dist/cjs/internal/Preserve.d.ts +25 -0
  209. package/dist/cjs/internal/Preserve.d.ts.map +1 -0
  210. package/dist/cjs/internal/Preserve.js +88 -0
  211. package/dist/cjs/internal/Preserve.js.map +7 -0
  212. package/dist/cjs/internal/Prune.d.ts +35 -0
  213. package/dist/cjs/internal/Prune.d.ts.map +1 -0
  214. package/dist/cjs/internal/Prune.js +54 -0
  215. package/dist/cjs/internal/Prune.js.map +7 -0
  216. package/dist/cjs/internal/SearchContract.d.ts +63 -0
  217. package/dist/cjs/internal/SearchContract.d.ts.map +1 -0
  218. package/dist/cjs/internal/SearchContract.js +46 -0
  219. package/dist/cjs/internal/SearchContract.js.map +7 -0
  220. package/dist/cjs/internal/Symbols.d.ts +39 -0
  221. package/dist/cjs/internal/Symbols.d.ts.map +1 -0
  222. package/dist/cjs/internal/Symbols.js +59 -0
  223. package/dist/cjs/internal/Symbols.js.map +7 -0
  224. package/dist/cjs/internal/TestReport.d.ts +52 -0
  225. package/dist/cjs/internal/TestReport.d.ts.map +1 -0
  226. package/dist/cjs/internal/TestReport.js +131 -0
  227. package/dist/cjs/internal/TestReport.js.map +7 -0
  228. package/dist/cjs/internal/Text.d.ts +114 -0
  229. package/dist/cjs/internal/Text.d.ts.map +1 -0
  230. package/dist/cjs/internal/Text.js +82 -0
  231. package/dist/cjs/internal/Text.js.map +7 -0
  232. package/dist/cjs/internal/Url.d.ts +13 -0
  233. package/dist/cjs/internal/Url.d.ts.map +1 -0
  234. package/dist/cjs/internal/Url.js +35 -0
  235. package/dist/cjs/internal/Url.js.map +7 -0
  236. package/dist/cjs/internal/Walk.d.ts +72 -0
  237. package/dist/cjs/internal/Walk.d.ts.map +1 -0
  238. package/dist/cjs/internal/Walk.js +108 -0
  239. package/dist/cjs/internal/Walk.js.map +7 -0
  240. package/dist/cjs/package.json +1 -0
  241. package/dist/esm/ApplyPatch.d.ts +174 -0
  242. package/dist/esm/ApplyPatch.d.ts.map +1 -0
  243. package/dist/esm/ApplyPatch.js +346 -0
  244. package/dist/esm/ApplyPatch.js.map +1 -0
  245. package/dist/esm/Bash.d.ts +380 -0
  246. package/dist/esm/Bash.d.ts.map +1 -0
  247. package/dist/esm/Bash.js +505 -0
  248. package/dist/esm/Bash.js.map +1 -0
  249. package/dist/esm/Checkpoints.d.ts +279 -0
  250. package/dist/esm/Checkpoints.d.ts.map +1 -0
  251. package/dist/esm/Checkpoints.js +298 -0
  252. package/dist/esm/Checkpoints.js.map +1 -0
  253. package/dist/esm/Container.d.ts +132 -0
  254. package/dist/esm/Container.d.ts.map +1 -0
  255. package/dist/esm/Container.js +151 -0
  256. package/dist/esm/Container.js.map +1 -0
  257. package/dist/esm/Edit.d.ts +203 -0
  258. package/dist/esm/Edit.d.ts.map +1 -0
  259. package/dist/esm/Edit.js +296 -0
  260. package/dist/esm/Edit.js.map +1 -0
  261. package/dist/esm/ExaWebSearch.d.ts +22 -0
  262. package/dist/esm/ExaWebSearch.d.ts.map +1 -0
  263. package/dist/esm/ExaWebSearch.js +107 -0
  264. package/dist/esm/ExaWebSearch.js.map +1 -0
  265. package/dist/esm/Explore.d.ts +328 -0
  266. package/dist/esm/Explore.d.ts.map +1 -0
  267. package/dist/esm/Explore.js +106 -0
  268. package/dist/esm/Explore.js.map +1 -0
  269. package/dist/esm/Fetch.d.ts +130 -0
  270. package/dist/esm/Fetch.d.ts.map +1 -0
  271. package/dist/esm/Fetch.js +91 -0
  272. package/dist/esm/Fetch.js.map +1 -0
  273. package/dist/esm/Glob.d.ts +204 -0
  274. package/dist/esm/Glob.d.ts.map +1 -0
  275. package/dist/esm/Glob.js +177 -0
  276. package/dist/esm/Glob.js.map +1 -0
  277. package/dist/esm/Grep.d.ts +347 -0
  278. package/dist/esm/Grep.d.ts.map +1 -0
  279. package/dist/esm/Grep.js +289 -0
  280. package/dist/esm/Grep.js.map +1 -0
  281. package/dist/esm/HttpPost.d.ts +130 -0
  282. package/dist/esm/HttpPost.d.ts.map +1 -0
  283. package/dist/esm/HttpPost.js +89 -0
  284. package/dist/esm/HttpPost.js.map +1 -0
  285. package/dist/esm/LanguageServer.d.ts +90 -0
  286. package/dist/esm/LanguageServer.d.ts.map +1 -0
  287. package/dist/esm/LanguageServer.js +57 -0
  288. package/dist/esm/LanguageServer.js.map +1 -0
  289. package/dist/esm/Ls.d.ts +164 -0
  290. package/dist/esm/Ls.d.ts.map +1 -0
  291. package/dist/esm/Ls.js +178 -0
  292. package/dist/esm/Ls.js.map +1 -0
  293. package/dist/esm/Lsp.d.ts +125 -0
  294. package/dist/esm/Lsp.d.ts.map +1 -0
  295. package/dist/esm/Lsp.js +165 -0
  296. package/dist/esm/Lsp.js.map +1 -0
  297. package/dist/esm/Manifest.d.ts +918 -0
  298. package/dist/esm/Manifest.d.ts.map +1 -0
  299. package/dist/esm/Manifest.js +153 -0
  300. package/dist/esm/Manifest.js.map +1 -0
  301. package/dist/esm/NativeSearch.d.ts +38 -0
  302. package/dist/esm/NativeSearch.d.ts.map +1 -0
  303. package/dist/esm/NativeSearch.js +378 -0
  304. package/dist/esm/NativeSearch.js.map +1 -0
  305. package/dist/esm/NodeLanguageServer.d.ts +128 -0
  306. package/dist/esm/NodeLanguageServer.d.ts.map +1 -0
  307. package/dist/esm/NodeLanguageServer.js +843 -0
  308. package/dist/esm/NodeLanguageServer.js.map +1 -0
  309. package/dist/esm/PortableSearch.d.ts +24 -0
  310. package/dist/esm/PortableSearch.d.ts.map +1 -0
  311. package/dist/esm/PortableSearch.js +240 -0
  312. package/dist/esm/PortableSearch.js.map +1 -0
  313. package/dist/esm/Probe.d.ts +193 -0
  314. package/dist/esm/Probe.d.ts.map +1 -0
  315. package/dist/esm/Probe.js +225 -0
  316. package/dist/esm/Probe.js.map +1 -0
  317. package/dist/esm/Read.d.ts +189 -0
  318. package/dist/esm/Read.d.ts.map +1 -0
  319. package/dist/esm/Read.js +300 -0
  320. package/dist/esm/Read.js.map +1 -0
  321. package/dist/esm/Relocate.d.ts +73 -0
  322. package/dist/esm/Relocate.d.ts.map +1 -0
  323. package/dist/esm/Relocate.js +153 -0
  324. package/dist/esm/Relocate.js.map +1 -0
  325. package/dist/esm/Search.d.ts +163 -0
  326. package/dist/esm/Search.d.ts.map +1 -0
  327. package/dist/esm/Search.js +47 -0
  328. package/dist/esm/Search.js.map +1 -0
  329. package/dist/esm/SearchConformance.d.ts +115 -0
  330. package/dist/esm/SearchConformance.d.ts.map +1 -0
  331. package/dist/esm/SearchConformance.js +193 -0
  332. package/dist/esm/SearchConformance.js.map +1 -0
  333. package/dist/esm/SearchContract.d.ts +114 -0
  334. package/dist/esm/SearchContract.d.ts.map +1 -0
  335. package/dist/esm/SearchContract.js +461 -0
  336. package/dist/esm/SearchContract.js.map +1 -0
  337. package/dist/esm/ShellCommand.d.ts +164 -0
  338. package/dist/esm/ShellCommand.d.ts.map +1 -0
  339. package/dist/esm/ShellCommand.js +159 -0
  340. package/dist/esm/ShellCommand.js.map +1 -0
  341. package/dist/esm/StdError.d.ts +55 -0
  342. package/dist/esm/StdError.d.ts.map +1 -0
  343. package/dist/esm/StdError.js +71 -0
  344. package/dist/esm/StdError.js.map +1 -0
  345. package/dist/esm/TestRun.d.ts +311 -0
  346. package/dist/esm/TestRun.d.ts.map +1 -0
  347. package/dist/esm/TestRun.js +316 -0
  348. package/dist/esm/TestRun.js.map +1 -0
  349. package/dist/esm/TestRunner.d.ts +102 -0
  350. package/dist/esm/TestRunner.d.ts.map +1 -0
  351. package/dist/esm/TestRunner.js +68 -0
  352. package/dist/esm/TestRunner.js.map +1 -0
  353. package/dist/esm/TreeFingerprint.d.ts +140 -0
  354. package/dist/esm/TreeFingerprint.d.ts.map +1 -0
  355. package/dist/esm/TreeFingerprint.js +170 -0
  356. package/dist/esm/TreeFingerprint.js.map +1 -0
  357. package/dist/esm/UpdatePlan.d.ts +152 -0
  358. package/dist/esm/UpdatePlan.d.ts.map +1 -0
  359. package/dist/esm/UpdatePlan.js +129 -0
  360. package/dist/esm/UpdatePlan.js.map +1 -0
  361. package/dist/esm/WebFetch.d.ts +134 -0
  362. package/dist/esm/WebFetch.d.ts.map +1 -0
  363. package/dist/esm/WebFetch.js +151 -0
  364. package/dist/esm/WebFetch.js.map +1 -0
  365. package/dist/esm/WebSearch.d.ts +181 -0
  366. package/dist/esm/WebSearch.d.ts.map +1 -0
  367. package/dist/esm/WebSearch.js +134 -0
  368. package/dist/esm/WebSearch.js.map +1 -0
  369. package/dist/esm/Write.d.ts +147 -0
  370. package/dist/esm/Write.d.ts.map +1 -0
  371. package/dist/esm/Write.js +144 -0
  372. package/dist/esm/Write.js.map +1 -0
  373. package/dist/esm/index.d.ts +127 -0
  374. package/dist/esm/index.d.ts.map +1 -0
  375. package/dist/esm/index.js +127 -0
  376. package/dist/esm/index.js.map +1 -0
  377. package/dist/esm/internal/ApplyPatch.d.ts +145 -0
  378. package/dist/esm/internal/ApplyPatch.d.ts.map +1 -0
  379. package/dist/esm/internal/ApplyPatch.js +489 -0
  380. package/dist/esm/internal/ApplyPatch.js.map +1 -0
  381. package/dist/esm/internal/CodexText.d.ts +73 -0
  382. package/dist/esm/internal/CodexText.d.ts.map +1 -0
  383. package/dist/esm/internal/CodexText.js +156 -0
  384. package/dist/esm/internal/CodexText.js.map +1 -0
  385. package/dist/esm/internal/Declaration.d.ts +49 -0
  386. package/dist/esm/internal/Declaration.d.ts.map +1 -0
  387. package/dist/esm/internal/Declaration.js +42 -0
  388. package/dist/esm/internal/Declaration.js.map +1 -0
  389. package/dist/esm/internal/Diagnostics.d.ts +77 -0
  390. package/dist/esm/internal/Diagnostics.d.ts.map +1 -0
  391. package/dist/esm/internal/Diagnostics.js +99 -0
  392. package/dist/esm/internal/Diagnostics.js.map +1 -0
  393. package/dist/esm/internal/EnvelopePrecheck.d.ts +67 -0
  394. package/dist/esm/internal/EnvelopePrecheck.d.ts.map +1 -0
  395. package/dist/esm/internal/EnvelopePrecheck.js +167 -0
  396. package/dist/esm/internal/EnvelopePrecheck.js.map +1 -0
  397. package/dist/esm/internal/Exec.d.ts +139 -0
  398. package/dist/esm/internal/Exec.d.ts.map +1 -0
  399. package/dist/esm/internal/Exec.js +193 -0
  400. package/dist/esm/internal/Exec.js.map +1 -0
  401. package/dist/esm/internal/FileMutation.d.ts +109 -0
  402. package/dist/esm/internal/FileMutation.d.ts.map +1 -0
  403. package/dist/esm/internal/FileMutation.js +123 -0
  404. package/dist/esm/internal/FileMutation.js.map +1 -0
  405. package/dist/esm/internal/FsFailure.d.ts +38 -0
  406. package/dist/esm/internal/FsFailure.d.ts.map +1 -0
  407. package/dist/esm/internal/FsFailure.js +39 -0
  408. package/dist/esm/internal/FsFailure.js.map +1 -0
  409. package/dist/esm/internal/GitWorktree.d.ts +108 -0
  410. package/dist/esm/internal/GitWorktree.d.ts.map +1 -0
  411. package/dist/esm/internal/GitWorktree.js +352 -0
  412. package/dist/esm/internal/GitWorktree.js.map +1 -0
  413. package/dist/esm/internal/Grouping.d.ts +51 -0
  414. package/dist/esm/internal/Grouping.d.ts.map +1 -0
  415. package/dist/esm/internal/Grouping.js +99 -0
  416. package/dist/esm/internal/Grouping.js.map +1 -0
  417. package/dist/esm/internal/Html.d.ts +20 -0
  418. package/dist/esm/internal/Html.d.ts.map +1 -0
  419. package/dist/esm/internal/Html.js +70 -0
  420. package/dist/esm/internal/Html.js.map +1 -0
  421. package/dist/esm/internal/Http.d.ts +95 -0
  422. package/dist/esm/internal/Http.d.ts.map +1 -0
  423. package/dist/esm/internal/Http.js +154 -0
  424. package/dist/esm/internal/Http.js.map +1 -0
  425. package/dist/esm/internal/HttpNetwork.d.ts +27 -0
  426. package/dist/esm/internal/HttpNetwork.d.ts.map +1 -0
  427. package/dist/esm/internal/HttpNetwork.js +114 -0
  428. package/dist/esm/internal/HttpNetwork.js.map +1 -0
  429. package/dist/esm/internal/Ignore.d.ts +37 -0
  430. package/dist/esm/internal/Ignore.d.ts.map +1 -0
  431. package/dist/esm/internal/Ignore.js +128 -0
  432. package/dist/esm/internal/Ignore.js.map +1 -0
  433. package/dist/esm/internal/LinearRegex.d.ts +19 -0
  434. package/dist/esm/internal/LinearRegex.d.ts.map +1 -0
  435. package/dist/esm/internal/LinearRegex.js +176 -0
  436. package/dist/esm/internal/LinearRegex.js.map +1 -0
  437. package/dist/esm/internal/Match.d.ts +85 -0
  438. package/dist/esm/internal/Match.d.ts.map +1 -0
  439. package/dist/esm/internal/Match.js +142 -0
  440. package/dist/esm/internal/Match.js.map +1 -0
  441. package/dist/esm/internal/Paths.d.ts +23 -0
  442. package/dist/esm/internal/Paths.d.ts.map +1 -0
  443. package/dist/esm/internal/Paths.js +40 -0
  444. package/dist/esm/internal/Paths.js.map +1 -0
  445. package/dist/esm/internal/Preserve.d.ts +25 -0
  446. package/dist/esm/internal/Preserve.d.ts.map +1 -0
  447. package/dist/esm/internal/Preserve.js +70 -0
  448. package/dist/esm/internal/Preserve.js.map +1 -0
  449. package/dist/esm/internal/Prune.d.ts +35 -0
  450. package/dist/esm/internal/Prune.d.ts.map +1 -0
  451. package/dist/esm/internal/Prune.js +60 -0
  452. package/dist/esm/internal/Prune.js.map +1 -0
  453. package/dist/esm/internal/SearchContract.d.ts +63 -0
  454. package/dist/esm/internal/SearchContract.d.ts.map +1 -0
  455. package/dist/esm/internal/SearchContract.js +66 -0
  456. package/dist/esm/internal/SearchContract.js.map +1 -0
  457. package/dist/esm/internal/Symbols.d.ts +39 -0
  458. package/dist/esm/internal/Symbols.d.ts.map +1 -0
  459. package/dist/esm/internal/Symbols.js +79 -0
  460. package/dist/esm/internal/Symbols.js.map +1 -0
  461. package/dist/esm/internal/TestReport.d.ts +52 -0
  462. package/dist/esm/internal/TestReport.d.ts.map +1 -0
  463. package/dist/esm/internal/TestReport.js +172 -0
  464. package/dist/esm/internal/TestReport.js.map +1 -0
  465. package/dist/esm/internal/Text.d.ts +114 -0
  466. package/dist/esm/internal/Text.d.ts.map +1 -0
  467. package/dist/esm/internal/Text.js +130 -0
  468. package/dist/esm/internal/Text.js.map +1 -0
  469. package/dist/esm/internal/Url.d.ts +13 -0
  470. package/dist/esm/internal/Url.d.ts.map +1 -0
  471. package/dist/esm/internal/Url.js +27 -0
  472. package/dist/esm/internal/Url.js.map +1 -0
  473. package/dist/esm/internal/Walk.d.ts +72 -0
  474. package/dist/esm/internal/Walk.d.ts.map +1 -0
  475. package/dist/esm/internal/Walk.js +126 -0
  476. package/dist/esm/internal/Walk.js.map +1 -0
  477. package/docs/README.md +117 -0
  478. package/docs/api.md +472 -0
  479. package/docs/concepts/effects-and-capabilities.md +136 -0
  480. package/docs/concepts/flows-and-handlers.md +115 -0
  481. package/docs/concepts/limits-and-disclosure.md +102 -0
  482. package/docs/concepts/search-contract.md +182 -0
  483. package/docs/guides/bind-the-standard-flows.md +114 -0
  484. package/docs/guides/implement-a-search-peer.md +133 -0
  485. package/docs/guides/pin-a-checkpoint.md +141 -0
  486. package/docs/guides/query-a-language-server.md +257 -0
  487. package/docs/guides/reach-the-network.md +141 -0
  488. package/docs/guides/read-and-edit-a-file.md +240 -0
  489. package/docs/guides/run-a-shell-command.md +215 -0
  490. package/docs/guides/run-the-test-suite.md +154 -0
  491. package/docs/guides/search-a-workspace.md +148 -0
  492. package/docs/installation.md +111 -0
  493. package/docs/quickstart.md +125 -0
  494. package/docs/reference/flows.md +556 -0
  495. package/docs/troubleshooting.md +322 -0
  496. package/package.json +439 -3
  497. package/src/ApplyPatch.ts +458 -0
  498. package/src/Bash.ts +607 -0
  499. package/src/Checkpoints.ts +422 -0
  500. package/src/Container.ts +212 -0
  501. package/src/Edit.ts +366 -0
  502. package/src/ExaWebSearch.ts +145 -0
  503. package/src/Explore.ts +139 -0
  504. package/src/Fetch.ts +117 -0
  505. package/src/Glob.ts +200 -0
  506. package/src/Grep.ts +320 -0
  507. package/src/HttpPost.ts +120 -0
  508. package/src/LanguageServer.ts +110 -0
  509. package/src/Ls.ts +228 -0
  510. package/src/Lsp.ts +184 -0
  511. package/src/Manifest.ts +162 -0
  512. package/src/NativeSearch.ts +457 -0
  513. package/src/NodeLanguageServer.ts +1148 -0
  514. package/src/PortableSearch.ts +264 -0
  515. package/src/Probe.ts +284 -0
  516. package/src/Read.ts +359 -0
  517. package/src/Relocate.ts +166 -0
  518. package/src/Search.ts +185 -0
  519. package/src/SearchConformance.ts +288 -0
  520. package/src/SearchContract.ts +489 -0
  521. package/src/ShellCommand.ts +201 -0
  522. package/src/StdError.ts +80 -0
  523. package/src/TestRun.ts +401 -0
  524. package/src/TestRunner.ts +119 -0
  525. package/src/TreeFingerprint.ts +200 -0
  526. package/src/UpdatePlan.ts +171 -0
  527. package/src/WebFetch.ts +194 -0
  528. package/src/WebSearch.ts +165 -0
  529. package/src/Write.ts +195 -0
  530. package/src/index.ts +154 -0
  531. package/src/internal/ApplyPatch.ts +601 -0
  532. package/src/internal/CodexText.ts +182 -0
  533. package/src/internal/Declaration.ts +60 -0
  534. package/src/internal/Diagnostics.ts +134 -0
  535. package/src/internal/EnvelopePrecheck.ts +233 -0
  536. package/src/internal/Exec.ts +314 -0
  537. package/src/internal/FileMutation.ts +231 -0
  538. package/src/internal/FsFailure.ts +51 -0
  539. package/src/internal/GitWorktree.ts +491 -0
  540. package/src/internal/Grouping.ts +106 -0
  541. package/src/internal/Html.ts +87 -0
  542. package/src/internal/Http.ts +209 -0
  543. package/src/internal/HttpNetwork.ts +153 -0
  544. package/src/internal/Ignore.ts +135 -0
  545. package/src/internal/LinearRegex.ts +173 -0
  546. package/src/internal/Match.ts +172 -0
  547. package/src/internal/Paths.ts +42 -0
  548. package/src/internal/Preserve.ts +108 -0
  549. package/src/internal/Prune.ts +62 -0
  550. package/src/internal/SearchContract.ts +77 -0
  551. package/src/internal/Symbols.ts +88 -0
  552. package/src/internal/TestReport.ts +194 -0
  553. package/src/internal/Text.ts +170 -0
  554. package/src/internal/Url.ts +23 -0
  555. package/src/internal/Walk.ts +176 -0
@@ -0,0 +1,422 @@
1
+ /**
2
+ * Pinned trees, and the scratch checkouts a call runs against.
3
+ *
4
+ * A checkpoint is a **value**: minting one changes nothing about the workspace,
5
+ * and running a call against one leaves the live tree exactly as it stands.
6
+ * That is the whole of what it buys. Before it existed, the only way a run
7
+ * could answer "did this command fail before my change" was to undo the change
8
+ * — and the journals price that exactly. On `sympy__sympy-13878` the r95repl
9
+ * lane applied one byte-identical 4,789-character patch **five times**, four of
10
+ * those applications preceded by `git checkout -- sympy/stats/crv_types.py`,
11
+ * because a clean fails-before proof required reverting the very work it was
12
+ * meant to prove.
13
+ *
14
+ * This module is the host half of `@smthrs/harness`'s `ctx.checkpoint()` and
15
+ * `ctx.call(flow, input, { at })`. The harness owns the surface, the identity,
16
+ * the bound and the refusals; nothing in it knows what a tree is. This owns the
17
+ * two host operations that need one:
18
+ *
19
+ * - {@link Checkpoints.capture} records the working tree under an id, and
20
+ * - {@link Checkpoints.materialize} gives that tree back as a directory for the
21
+ * length of one call.
22
+ *
23
+ * ## The git binding, and the container constraint it is shaped by
24
+ *
25
+ * {@link layerGit} records a checkpoint with `git stash create`, then names the
26
+ * commit it prints in this repository's own git config rather than with a ref —
27
+ * see {@link configSection} for why a ref would hand the agent its own edit back
28
+ * as history. `stash create` is the one git command
29
+ * that records the working tree and changes nothing else: it does not move the
30
+ * worktree and does not touch the stash ref. It runs against a shadow
31
+ * `GIT_DIR` over a copy of the workspace index (see `internal/GitWorktree.ts`),
32
+ * so it never writes the repository's index and never runs a program the
33
+ * workspace's `.git` names. That matters more than it sounds. The agent runs `git` in this same
34
+ * workspace and its own `git diff` is the run's evidence, so a capture that
35
+ * staged into the real index would be the harness editing the evidence while
36
+ * recording it. A tree with nothing to record prints nothing, and the
37
+ * checkpoint is then `HEAD` — which is exactly what the tree is.
38
+ *
39
+ * Untracked files are not in the recorded tree, which matches how the rig
40
+ * captures a patch: `capture-patch.sh` drops paths that did not exist when the
41
+ * agent started, so a checkpoint holds what a patch would hold.
42
+ *
43
+ * The materialization is a detached checkout at `<root>/.flows-checkpoints/<id>-<lease>`
44
+ * — **inside** the workspace, which looks wrong and is the only thing that
45
+ * works. A benchmark check runs through `docker exec` inside `/testbed`, and
46
+ * `/testbed` is a bind mount of the live workspace. A scratch checkout anywhere
47
+ * else on the host is simply not visible to the container, so the call would run
48
+ * against a path that does not exist. Placed under the workspace it is visible
49
+ * at the same subpath under the mount, needs no second mount, and needs no
50
+ * change to how the rig starts its container. `TestRun`'s `against: "base"`
51
+ * reached the same conclusion first and this reuses its shape;
52
+ * `evals/swebench/run-instance.sh` excludes the directory from patch capture for
53
+ * the same reason it excludes `.flows-test-base`.
54
+ *
55
+ * The checkout is added and removed around **one call**, which is stricter than
56
+ * the frame lifetime the design asks for and much simpler: there is no cache to
57
+ * invalidate, no id to leak, and a checkpoint used by three calls pays three
58
+ * checkouts rather than risking one stale directory. A run that reuses a
59
+ * checkpoint across frames simply re-materializes it, because the ref is what
60
+ * persists.
61
+ *
62
+ * ## What can be pointed at a checkpoint, and what cannot
63
+ *
64
+ * {@link relocate} is the closed answer, and `Relocate.ts` owns it. That half
65
+ * knows the input shapes of `bash`, `read`, `ls`, `grep` and `glob`; this half
66
+ * knows git. They change for different reasons, so they are different modules,
67
+ * and {@link relocate} is re-exported here because the harness reaches the whole
68
+ * feature through this one.
69
+ *
70
+ * @since 1.0.0
71
+ */
72
+
73
+ import { ChildProcessSpawner } from "@smthrs/kernel/ChildProcessSpawner"
74
+ import { Context, Effect, Layer, Schema } from "effect"
75
+ import { GitWorktree } from "./internal/GitWorktree.ts"
76
+ import { withoutTrailingSlash } from "./internal/Paths.ts"
77
+ import * as Prune from "./internal/Prune.ts"
78
+ import * as StdError from "./StdError.ts"
79
+ import * as TestRunner from "./TestRunner.ts"
80
+
81
+ /**
82
+ * The id naming the tree a run opened on.
83
+ *
84
+ * It is not minted: the host either recorded one before the agent started or it
85
+ * did not. {@link layerGit} resolves it to {@link TestRunner.captureBase} and
86
+ * then to `HEAD`, which is the same precedence `TestRun` uses for the same
87
+ * question — so a workspace that has one answer for a baseline has one answer
88
+ * for both.
89
+ *
90
+ * @category constants
91
+ * @since 1.0.0
92
+ */
93
+ export const baseId = "base"
94
+
95
+ /**
96
+ * The directory checkpoints are materialized into, relative to the repository
97
+ * root and therefore also relative to a container's view of it.
98
+ *
99
+ * @category constants
100
+ * @since 1.0.0
101
+ */
102
+ export const scratchDirectory = Prune.checkpointScratch
103
+
104
+ /**
105
+ * The git-config section {@link layerGit} records minted checkpoints under.
106
+ *
107
+ * Config and **not a ref**, and that is the whole of the decision. A ref is
108
+ * history: `git log --all` lists it, `git show` prints it, and `git log --all
109
+ * -S` searches it — so a checkpoint named by a ref would hand an agent a commit
110
+ * containing its own edit and let it read that back as if it were upstream
111
+ * work. That exact class cost the measured program real money before the rig
112
+ * moved jj's store out of the workspace (`evals/swebench/run-instance.sh`:
113
+ * django-13346 applied two of its own snapshots as a fake fix), and a ref here
114
+ * would reintroduce it one wave later.
115
+ *
116
+ * The commit object itself is unreferenced. It stays alive for the life of the
117
+ * run — nothing in a run prunes — and a checkout by id works perfectly well,
118
+ * which is measured in `CheckpointsFixture.test.ts`. So the tree is reachable
119
+ * by id and no command that walks refs can reach it:
120
+ * `git log`, `git log --all`, `git log -S` and `git show <ref>` all answer
121
+ * exactly as they did before the capture.
122
+ *
123
+ * One command still sees it, measured rather than argued in
124
+ * `CheckpointsFixture.test.ts`: `git fsck` reports it as a dangling commit,
125
+ * because that is what an unreferenced commit is. A checkout is a standalone
126
+ * repository, not a worktree of this one, so `git log --all` does not list it
127
+ * even while a call runs in it. It is not reachable by a name that looks like project history, and the cell
128
+ * contract's environment section says outright that a dangling commit is this
129
+ * harness holding the agent's own tree — which is the half of the django-13346
130
+ * lesson that a store cannot enforce.
131
+ *
132
+ * @category constants
133
+ * @since 1.0.0
134
+ */
135
+ export const configSection = "flows-checkpoint"
136
+
137
+ /**
138
+ * One tree this run has pinned.
139
+ *
140
+ * `ref` is the store's own name for it. Nothing above this module interprets
141
+ * it; it travels so the journal says which tree a checkpointed call read.
142
+ *
143
+ * @category models
144
+ * @since 1.0.0
145
+ */
146
+ export class Snapshot extends Schema.Class<Snapshot>("@smthrs/std/Checkpoints/Snapshot")({
147
+ id: Schema.String,
148
+ ref: Schema.String
149
+ }) {}
150
+
151
+ /**
152
+ * A tree handed back as a directory, for the length of one call.
153
+ *
154
+ * `host` is where the process running on this machine finds it. `guest` is
155
+ * where a container finds the same directory, which is the same path when no
156
+ * container is in play. They differ exactly as `TestRunner.Runner`'s `cwd` and
157
+ * `root` differ, and for the same reason: one directory, two names.
158
+ *
159
+ * `root` and `guestRoot` are the workspace itself under those same two names.
160
+ * They travel because a call that named a directory *inside* the workspace has
161
+ * to keep it: a check that runs in `tests/` and is pointed at a checkpoint must
162
+ * run in the checkpoint's `tests/`, not at its top. Silently dropping that
163
+ * subpath is how a baseline comes back failing for a reason nobody chose, which
164
+ * is the one failure a checkpoint exists to make impossible.
165
+ *
166
+ * @category models
167
+ * @since 1.0.0
168
+ */
169
+ export interface Materialized {
170
+ readonly id: string
171
+ readonly host: string
172
+ readonly guest: string
173
+ /** The workspace this checkpoint is a tree of, as this machine names it. */
174
+ readonly root: string
175
+ /** The workspace as a container names it; the same as {@link Materialized.root} when none does. */
176
+ readonly guestRoot: string
177
+ }
178
+
179
+ /**
180
+ * The two host operations a checkpoint needs.
181
+ *
182
+ * @category services
183
+ * @since 1.0.0
184
+ */
185
+ export interface Checkpoints {
186
+ /** Records the working tree as it stands, under `id`. */
187
+ readonly capture: (id: string) => Effect.Effect<Snapshot, StdError.StdError>
188
+ /**
189
+ * Hands `id` back as a directory for the length of the effect it wraps.
190
+ *
191
+ * Scoped rather than returned, because the directory has to be removed
192
+ * however the call ends — a benchmark run killed at its wall-clock budget
193
+ * would otherwise leave a second checkout of the whole repository in a tree
194
+ * whose diff is the run's answer.
195
+ */
196
+ readonly materialize: <A, E, R>(
197
+ id: string,
198
+ use: (materialized: Materialized) => Effect.Effect<A, E, R>
199
+ ) => Effect.Effect<A, E | StdError.StdError, R>
200
+ }
201
+
202
+ /**
203
+ * The {@link Checkpoints} service tag.
204
+ *
205
+ * @category services
206
+ * @since 1.0.0
207
+ */
208
+ export const Checkpoints: Context.Service<Checkpoints, Checkpoints> = Context.Service("@smthrs/std/Checkpoints")
209
+
210
+ /**
211
+ * Builds a store from its two operations.
212
+ *
213
+ * @category constructors
214
+ * @since 1.0.0
215
+ */
216
+ export const make = (service: Checkpoints): Checkpoints => Checkpoints.of(service)
217
+
218
+ /**
219
+ * The refusal a host with nowhere to pin a tree answers with.
220
+ *
221
+ * @category errors
222
+ * @since 1.0.0
223
+ */
224
+ export const unavailable = (id: string): StdError.StdError =>
225
+ new StdError.StdError({
226
+ code: "provider_unavailable",
227
+ message: `This host pins no trees, so it holds no checkpoint "${id}". Take the reading on the live tree instead.`
228
+ })
229
+
230
+ /**
231
+ * Builds a store for a host that pins nothing.
232
+ *
233
+ * @category constructors
234
+ * @since 1.0.0
235
+ */
236
+ export const makeNoop = (): Checkpoints =>
237
+ make({
238
+ capture: (id) => Effect.fail(unavailable(id)),
239
+ materialize: (id) => Effect.fail(unavailable(id))
240
+ })
241
+
242
+ /**
243
+ * Provides {@link makeNoop}.
244
+ *
245
+ * @category layers
246
+ * @since 1.0.0
247
+ */
248
+ export const layerNoop: Layer.Layer<Checkpoints> = Layer.succeed(Checkpoints, makeNoop())
249
+
250
+ /**
251
+ * What {@link layerGit} needs to know about the repository it pins.
252
+ *
253
+ * @category models
254
+ * @since 1.0.0
255
+ */
256
+ export interface GitOptions {
257
+ /** The host path of the git repository whose trees are pinned. */
258
+ readonly root: string
259
+ /**
260
+ * Where a container sees {@link GitOptions.root}, when one does.
261
+ *
262
+ * Absent means there is no container, and the guest path of a materialized
263
+ * checkpoint is then its host path.
264
+ */
265
+ readonly cwd?: string | undefined
266
+ /**
267
+ * The ref naming the tree the run opened on, for {@link baseId}.
268
+ *
269
+ * Absent takes `TestRunner.captureBase` and then `HEAD`, which is the
270
+ * precedence `TestRun` already uses.
271
+ */
272
+ readonly baseRef?: string | undefined
273
+ }
274
+
275
+ const failed = (message: string, code: StdError.Code = "command_failed"): StdError.StdError =>
276
+ new StdError.StdError({ code, message })
277
+
278
+ /**
279
+ * A checkpoint id, restricted to what can safely become a git-config key and a
280
+ * directory name. No dots: a dot would split the config key into another
281
+ * subsection.
282
+ */
283
+ const namable = /^[A-Za-z0-9][A-Za-z0-9-]*$/
284
+
285
+ /**
286
+ * Builds the git-backed store.
287
+ *
288
+ * Every git command that records or checks out a tree runs against a shadow
289
+ * `GIT_DIR` the harness owns, never the workspace's `.git`, which the agent
290
+ * can write; see `internal/GitWorktree.ts`. The capture reads a copy of the
291
+ * workspace index, so the agent's own index is untouched: its `git diff` is the
292
+ * run's evidence and must not move because the harness recorded something.
293
+ *
294
+ * @category constructors
295
+ * @since 1.0.0
296
+ */
297
+ export const makeGit = (
298
+ options: GitOptions
299
+ ): Effect.Effect<Checkpoints, never, ChildProcessSpawner> =>
300
+ Effect.gen(function*() {
301
+ const spawner = yield* ChildProcessSpawner
302
+ return gitStore(options, spawner)
303
+ })
304
+
305
+ /**
306
+ * The store itself, with the spawner it runs git through already resolved.
307
+ *
308
+ * Resolving it here rather than threading it through {@link Checkpoints} keeps
309
+ * the service's own requirement empty, which is what lets a browser host bind
310
+ * {@link layerNoop} against the identical interface — the same shape
311
+ * `TestRunner` and `Container` take.
312
+ */
313
+ const gitStore = (options: GitOptions, spawner: ChildProcessSpawner["Service"]): Checkpoints => {
314
+ const spawn = <A, E>(effect: Effect.Effect<A, E, ChildProcessSpawner>): Effect.Effect<A, E> =>
315
+ Effect.provideService(effect, ChildProcessSpawner, spawner)
316
+ const root = withoutTrailingSlash(options.root)
317
+ const guestRoot = options.cwd === undefined ? root : withoutTrailingSlash(options.cwd)
318
+ const keyOf = (id: string) => `${configSection}.${id}`
319
+ const baseRefs = options.baseRef === undefined ? [TestRunner.captureBase, "HEAD"] : [options.baseRef]
320
+
321
+ /**
322
+ * The commit one id names.
323
+ *
324
+ * `base` is the one id nobody mints, so it is resolved from refs — the same
325
+ * precedence `TestRun` uses. Every other id was recorded by {@link capture}
326
+ * into this repository's config file, which is where a checkpoint is named
327
+ * *without* becoming history. See {@link configSection}.
328
+ */
329
+ const commitOf = (id: string) =>
330
+ Effect.gen(function*() {
331
+ if (id === baseId) return (yield* GitWorktree.resolveCommit(root, baseRefs)).commit
332
+ const repository = yield* GitWorktree.open(root)
333
+ const found = yield* GitWorktree.config(repository, ["--get", keyOf(id)])
334
+ const commit = found.stdout.trim()
335
+ if (found.exitCode !== 0 || commit === "") {
336
+ return yield* Effect.fail(
337
+ failed(
338
+ `No checkpoint is stored under ${id} in ${root}. Take the reading on the live tree instead.`,
339
+ "not_found"
340
+ )
341
+ )
342
+ }
343
+ return commit
344
+ })
345
+
346
+ const capture = (id: string) =>
347
+ spawn(Effect.gen(function*() {
348
+ if (!namable.test(id)) {
349
+ return yield* Effect.fail(
350
+ failed(`A checkpoint id must match ${namable.source}; ${id} does not.`, "invalid_input")
351
+ )
352
+ }
353
+ const repository = yield* GitWorktree.open(root)
354
+ const commit = yield* GitWorktree.withShadow(repository, (shadow) =>
355
+ Effect.gen(function*() {
356
+ const head = (yield* GitWorktree.resolveCommit(root, ["HEAD"])).commit
357
+ yield* shadow.adoptIndex
358
+ const pinned = yield* shadow.git(["update-ref", "--no-deref", "HEAD", head])
359
+ if (pinned.exitCode !== 0) {
360
+ return yield* Effect.fail(failed(`Could not record the working tree: ${pinned.stderr.trim()}`))
361
+ }
362
+ const recorded = yield* shadow.git(["stash", "create", `flows checkpoint ${id}`], root)
363
+ if (recorded.exitCode !== 0) {
364
+ return yield* Effect.fail(failed(`Could not record the working tree: ${recorded.stderr.trim()}`))
365
+ }
366
+ // Nothing to record means the working tree IS the commit it is on, so
367
+ // that commit is the checkpoint. `stash create` says so by printing
368
+ // nothing, which is not an error and must not be read as one.
369
+ return recorded.stdout.trim() === "" ? head : recorded.stdout.trim()
370
+ }))
371
+ const named = yield* GitWorktree.config(repository, [keyOf(id), commit])
372
+ if (named.exitCode !== 0) {
373
+ return yield* Effect.fail(failed(`Could not name the checkpoint: ${named.stderr.trim()}`))
374
+ }
375
+ return new Snapshot({ id, ref: commit })
376
+ }))
377
+
378
+ const materialize = <A, E, R>(
379
+ id: string,
380
+ use: (materialized: Materialized) => Effect.Effect<A, E, R>
381
+ ): Effect.Effect<A, E | StdError.StdError, R> =>
382
+ Effect.gen(function*() {
383
+ if (!namable.test(id)) {
384
+ return yield* Effect.fail(
385
+ failed(`A checkpoint id must match ${namable.source}; ${id} does not.`, "invalid_input")
386
+ )
387
+ }
388
+ const commit = yield* spawn(commitOf(id))
389
+ const context = yield* Effect.context<R>()
390
+ return yield* GitWorktree.withDetachedWorktree(
391
+ root,
392
+ `${scratchDirectory}/${id}`,
393
+ commit,
394
+ (host) =>
395
+ use({ id, host, guest: `${guestRoot}${host.slice(root.length)}`, root, guestRoot }).pipe(
396
+ Effect.provideContext(context)
397
+ )
398
+ ).pipe(Effect.provideService(ChildProcessSpawner, spawner))
399
+ })
400
+
401
+ return make({ capture, materialize })
402
+ }
403
+
404
+ /**
405
+ * Provides {@link makeGit}.
406
+ *
407
+ * @category layers
408
+ * @since 1.0.0
409
+ */
410
+ export const layerGit = (options: GitOptions): Layer.Layer<Checkpoints, never, ChildProcessSpawner> =>
411
+ Layer.effect(Checkpoints)(makeGit(options))
412
+ /**
413
+ * Rewrites one call's input so the call runs against a materialized checkpoint.
414
+ *
415
+ * Re-exported from {@link Relocate}, which owns the table of flows and fields
416
+ * this rewrite is driven by. It is exported here because the harness reaches the
417
+ * whole checkpoint feature through this module.
418
+ *
419
+ * @category conversions
420
+ * @since 1.0.0
421
+ */
422
+ export { relocate, type Relocation } from "./Relocate.ts"
@@ -0,0 +1,212 @@
1
+ /**
2
+ * The host's route into a named container, as an injected transport.
3
+ *
4
+ * A task whose interpreter, dependencies, and test runner live in a container
5
+ * makes every command a nested quoting problem: the agent writes
6
+ * `docker exec c bash -lc 'cd /testbed && python - <<EOF … EOF'`, and one layer
7
+ * of that stack eats a quote. The measured cost across the 45-instance program
8
+ * was twelve failed probes, one instance's single most expensive frame
9
+ * (astropy-8707, which produced a probe that never ran), and a class of failure
10
+ * that turns from a broken probe into a broken *edit* the moment the same
11
+ * quoting reaches a writing command.
12
+ *
13
+ * So the transport is the harness's, not the agent's. A caller names the
14
+ * container and passes its program and payload as data; this service turns that
15
+ * into the argv the host actually spawns. `docker` and `podman` share the CLI
16
+ * {@link makeCommand} builds, and a host with a different route supplies its own
17
+ * {@link make} rather than teaching the agent a new incantation.
18
+ *
19
+ * A host that has no container route provides {@link makeNoop}, whose refusal
20
+ * says so plainly. Nothing here shells out on its own: it only decides an argv,
21
+ * and `bash` spawns it through the same permission-aware spawner as everything
22
+ * else.
23
+ *
24
+ * @since 1.0.0
25
+ */
26
+
27
+ import { Context, Effect, Layer } from "effect"
28
+ import * as StdError from "./StdError.ts"
29
+
30
+ /**
31
+ * One command to run inside a container.
32
+ *
33
+ * @category models
34
+ * @since 1.0.0
35
+ */
36
+ export interface Request {
37
+ readonly container: string
38
+ readonly file: string
39
+ readonly args: ReadonlyArray<string>
40
+ readonly cwd?: string | undefined
41
+ readonly env?: Record<string, string> | undefined
42
+ /** Whether the payload arrives on the program's standard input. */
43
+ readonly stdin: boolean
44
+ }
45
+
46
+ /**
47
+ * The argv the host spawns to satisfy a {@link Request}.
48
+ *
49
+ * @category models
50
+ * @since 1.0.0
51
+ */
52
+ export interface Plan {
53
+ readonly file: string
54
+ readonly args: ReadonlyArray<string>
55
+ /** Environment overrides for the transport process, never rendered as argv. */
56
+ readonly env?: Record<string, string> | undefined
57
+ }
58
+
59
+ /**
60
+ * The one container transport contract.
61
+ *
62
+ * @category services
63
+ * @since 1.0.0
64
+ */
65
+ export interface Container {
66
+ readonly exec: (request: Request) => Effect.Effect<Plan, StdError.StdError>
67
+ }
68
+
69
+ /**
70
+ * The {@link Container} service tag.
71
+ *
72
+ * @category services
73
+ * @since 1.0.0
74
+ */
75
+ export const Container: Context.Service<Container, Container> = Context.Service("@smthrs/std/Container")
76
+
77
+ /**
78
+ * Builds a container transport from its one operation.
79
+ *
80
+ * @category constructors
81
+ * @since 1.0.0
82
+ */
83
+ export const make = (service: Container): Container => Container.of(service)
84
+
85
+ /**
86
+ * The refusal a host with no container route answers with.
87
+ *
88
+ * @category errors
89
+ * @since 1.0.0
90
+ */
91
+ export const unavailable = (container: string): StdError.StdError =>
92
+ new StdError.StdError({
93
+ code: "provider_unavailable",
94
+ message:
95
+ `This host has no container transport, so it cannot run anything in "${container}". Drop the container field and run the command here, or ask the host to bind one.`
96
+ })
97
+
98
+ /**
99
+ * Builds the transport for a host with no container route.
100
+ *
101
+ * @category constructors
102
+ * @since 1.0.0
103
+ */
104
+ export const makeNoop = (): Container => make({ exec: (request) => Effect.fail(unavailable(request.container)) })
105
+
106
+ /**
107
+ * Provides {@link makeNoop}.
108
+ *
109
+ * @category layers
110
+ * @since 1.0.0
111
+ */
112
+ export const layerNoop: Layer.Layer<Container> = Layer.succeed(Container, makeNoop())
113
+
114
+ /** The names a forwarded environment variable may take: a POSIX shell name. */
115
+ const environmentName = /^[A-Za-z_][A-Za-z0-9_]*$/
116
+
117
+ /** The prefix a forwarded variable carries on the host transport process. */
118
+ const forwardedPrefix = "SMITHERS_CONTAINER_ENV_"
119
+
120
+ /** The in-container script that renames each forwarded variable, then runs the program. */
121
+ const rename = (names: ReadonlyArray<string>): string =>
122
+ [
123
+ ...names.map((key) => `${key}="$${forwardedPrefix}${key}"; export ${key}; unset ${forwardedPrefix}${key}`),
124
+ `exec "$@"`
125
+ ].join("; ")
126
+
127
+ /**
128
+ * Builds a transport over a `docker exec`-compatible CLI.
129
+ *
130
+ * `-i` is attached only when the payload arrives on standard input, because a
131
+ * container CLI that holds stdin open for a command that never reads it makes
132
+ * that command hang.
133
+ *
134
+ * Requested environment variables never reach the transport process under
135
+ * their own names. The request's `env` is the caller's, and the transport is a
136
+ * host program: `PATH`, `LD_PRELOAD`, `DOCKER_HOST` or `XDG_CONFIG_HOME` set on
137
+ * it would choose what runs on the host. Each value therefore travels in
138
+ * {@link Plan.env} under `SMITHERS_CONTAINER_ENV_`, is forwarded by that name
139
+ * (`-e SMITHERS_CONTAINER_ENV_KEY`), and a `sh` inside the container renames it
140
+ * to `KEY` before `exec`ing the program. Values stay out of the argv. A name
141
+ * must be a POSIX shell name. A request with `env` therefore requires `sh` in
142
+ * the container; one without `env` runs the program directly, so an image
143
+ * without a shell works only for requests that carry no `env`.
144
+ *
145
+ * @category constructors
146
+ * @since 1.0.0
147
+ */
148
+ export const makeCommand = (options?: { readonly program?: string | undefined }): Container => {
149
+ const program = options?.program ?? "docker"
150
+ return make({
151
+ exec: (request) => {
152
+ const env = request.env
153
+ const entries = Object.entries(env ?? {})
154
+ const names = entries.map(([key]) => key)
155
+ const invalid = names.find((key) => !environmentName.test(key))
156
+ if (invalid !== undefined) {
157
+ return Effect.fail(
158
+ new StdError.StdError({
159
+ code: "invalid_input",
160
+ message: `Environment variable names must match ${environmentName.source}: ${invalid}`
161
+ })
162
+ )
163
+ }
164
+ if (request.container === "" || request.container.startsWith("-")) {
165
+ return Effect.fail(
166
+ new StdError.StdError({
167
+ code: "invalid_input",
168
+ message: `Container name must be non-empty and cannot start with '-': ${request.container}`,
169
+ path: request.container
170
+ })
171
+ )
172
+ }
173
+ const args = Array.from(request.args)
174
+ if (args.some((arg) => typeof arg !== "string")) {
175
+ return Effect.fail(
176
+ new StdError.StdError({
177
+ code: "invalid_input",
178
+ message: "Container arguments must be a dense array of strings."
179
+ })
180
+ )
181
+ }
182
+ return Effect.succeed({
183
+ file: program,
184
+ args: [
185
+ "exec",
186
+ ...(request.stdin ? ["-i"] : []),
187
+ ...(request.cwd === undefined ? [] : ["-w", request.cwd]),
188
+ ...names.flatMap((key) => ["-e", `${forwardedPrefix}${key}`]),
189
+ "--",
190
+ request.container,
191
+ ...(names.length === 0 ? [] : ["sh", "-c", rename(names), "sh"]),
192
+ request.file,
193
+ ...args
194
+ ],
195
+ ...(env === undefined ? {} : {
196
+ env: Object.fromEntries(
197
+ entries.map(([key, value]) => [`${forwardedPrefix}${key}`, value])
198
+ )
199
+ })
200
+ })
201
+ }
202
+ })
203
+ }
204
+
205
+ /**
206
+ * Provides {@link makeCommand}.
207
+ *
208
+ * @category layers
209
+ * @since 1.0.0
210
+ */
211
+ export const layerCommand = (options?: { readonly program?: string | undefined }): Layer.Layer<Container> =>
212
+ Layer.succeed(Container, makeCommand(options))