@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,240 @@
1
+ ---
2
+ title: "Read and edit a file"
3
+ description: "Page a file with read, anchor an edit by exact text or by an earlier hit's line range, and read what a miss reports back so the next attempt lands."
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ Four flows cover a file: `read`, `write`, `edit`, and `apply_patch`. This guide
9
+ is about the loop that matters, which is reading a region and then changing it
10
+ without losing the anchor in between.
11
+
12
+ ## Read a page
13
+
14
+ ```ts
15
+ import * as Read from "@smthrs/std/Read"
16
+
17
+ const page = Read.run({ path: "/workspace/src/widen.ts", offset: 40, limit: 20 })
18
+ ```
19
+
20
+ `offset` and `limit` are 1-based lines. With neither, you get the first 2,000
21
+ lines. The result is:
22
+
23
+ | Field | Meaning |
24
+ | ---------------------- | ------------------------------------------------------- |
25
+ | `content` | Raw page text, byte for byte as the file holds it. |
26
+ | `startLine`, `endLine` | The 1-based range this page covers. |
27
+ | `totalLines` | The file's line count. |
28
+ | `truncated` | Whether anything was cut. |
29
+ | `notice` | What was shown out of what there was, when `truncated`. |
30
+
31
+ `content` carries no line-number gutter. That is deliberate: an anchor copied
32
+ out of a numbered read carries the numbers with it, so every `edit` built from
33
+ one misses. Line numbers are facts about the page, so they are page fields.
34
+
35
+ Source lines split on `\n`. A trailing `\r` is part of the line, including in
36
+ CRLF files. Pages omit the final `\n` and retain every `\r`. For example,
37
+ `"one\r\ntwo\r\n"` reads as `"one\r\ntwo\r"`. Copy that text unchanged into
38
+ `oldString` or `expect`. Replacement text is also literal: retain the `\r`
39
+ bytes in `newString` to keep CRLF endings, including the last line of a range.
40
+ A line-range edit leaves the final `\n` outside the replaced span.
41
+
42
+ A page cut by the byte budget ends on a whole line rather than handing back a
43
+ fragment that looks like an anchor and is not one. A line longer than 2,000
44
+ characters is clipped, and the notice says so by name, because a clipped line
45
+ cannot be an anchor either.
46
+
47
+ Reading an empty file returns an empty page with `startLine: 1`, `endLine: 0`,
48
+ and `totalLines: 0`. Only an `offset` past the end is
49
+ `offset_out_of_range`. A directory is `is_directory`; a file holding a NUL byte
50
+ or invalid UTF-8 is `binary_file`.
51
+
52
+ ## Edit by exact text
53
+
54
+ The first anchor form is the file's own bytes:
55
+
56
+ ```ts
57
+ import * as Edit from "@smthrs/std/Edit"
58
+
59
+ const applied = Edit.run({
60
+ path: "/workspace/src/widen.ts",
61
+ oldString: " return value * 2",
62
+ newString: " return value * 3"
63
+ })
64
+ ```
65
+
66
+ The match is byte exact. There is no fuzzy fallback, because a match that is not
67
+ your bytes is an edit nobody inspected.
68
+
69
+ `oldString` must occur exactly once. When it occurs more than once, the call
70
+ fails with `invalid_input` naming every line the anchor sits on, so you can widen
71
+ it without re-reading the file. Pass `replaceAll: true` to change all of them on
72
+ purpose.
73
+
74
+ When it occurs nowhere, the call fails with `no_match`, and the message carries
75
+ the file's **actual** bytes at the nearest region, with that region's line range:
76
+
77
+ ```text
78
+ oldString does not occur in /workspace/src/widen.ts. Lines 1-3 actually hold this, raw:
79
+ export function widen(value: number): number {
80
+ return value * 2
81
+ }
82
+
83
+ Copy the lines you meant from that text, or anchor by startLine/endLine instead.
84
+ ```
85
+
86
+ When not even one line of the anchor occurs in the file, the message says that
87
+ instead: the file is the wrong one, or the region is not what you remember.
88
+
89
+ That is the point of the failure: re-anchor from reality inside the same frame,
90
+ rather than re-reading, re-guessing, and missing again.
91
+
92
+ ## Edit by line range
93
+
94
+ The second anchor form reuses a hit you already have from `read` or `grep`,
95
+ instead of retyping the text:
96
+
97
+ ```ts
98
+ const applied = Edit.run({
99
+ path: "/workspace/src/widen.ts",
100
+ startLine: 2,
101
+ endLine: 2,
102
+ expect: " return value * 2",
103
+ newString: " return value * 3"
104
+ })
105
+ ```
106
+
107
+ `startLine` and `endLine` are both required and inclusive. `expect` is optional
108
+ and turns the retyped copy into a checked assertion rather than a search key: if
109
+ those lines hold anything else, the call fails with `no_match` and prints what
110
+ they actually hold, which is what a file that moved under your line numbers looks
111
+ like.
112
+
113
+ The two forms do not mix. Each of these is `invalid_input`:
114
+
115
+ - `oldString` together with `startLine` or `endLine`.
116
+ - Neither `oldString` nor a line range. Use `write` to create a file.
117
+ - An empty `oldString`.
118
+ - `expect` together with `oldString`.
119
+ - `replaceAll` together with a line range.
120
+ - `endLine` before `startLine`.
121
+
122
+ A range past the end of the file is `offset_out_of_range`.
123
+
124
+ ## Read the hunk back
125
+
126
+ Every successful edit returns the region it wrote, raw, with two lines of
127
+ context on each side:
128
+
129
+ ```ts
130
+ // applied.startLine, applied.endLine: the range of the returned hunk
131
+ // applied.replacements: how many occurrences changed
132
+ // applied.hunk: the edited region as it now stands
133
+ ```
134
+
135
+ A mis-indented edit costs one glance at `hunk` instead of an investigation.
136
+
137
+ ## Concurrent changes
138
+
139
+ On ordinary filesystem hosts, `edit`, `write`, and `apply_patch` hold exclusive sibling directory locks from
140
+ before reading until their mutation finishes. Existing symlink aliases share
141
+ the resolved file's lock. Case and Unicode normalization variants conservatively
142
+ share a lock, even on a case-sensitive filesystem. Separate hosts and processes using these handlers
143
+ coordinate through the same filesystem; it must implement exclusive directory
144
+ creation. A competing call fails with `no_match` and names the busy file before
145
+ changing it. Re-read and retry after the other writer finishes. Anchors and
146
+ line-range `expect` are checked again on every retry.
147
+
148
+ A patch locks all source and destination paths before reading update contents.
149
+ It may create destination parent directories first. Failure to acquire any lock
150
+ releases the locks already acquired without applying file changes. Locks also
151
+ release on ordinary failure and Effect interruption. Process death leaves a
152
+ `.smithers-*.lock` directory and subsequent calls refuse to write. Stop all
153
+ writers for that file, inspect its contents, and remove only the lock named in
154
+ the refusal before retrying. Locks are never reclaimed by age.
155
+
156
+ These locks coordinate standard handlers sharing a filesystem, including patch
157
+ adds, deletes, and moves. Shell commands, editors, and other programs that do
158
+ not use this protocol are outside that guarantee. Whole-file `write` and patch
159
+ add operations intentionally replace contents; use an anchored edit when a
160
+ previously read version must still match.
161
+
162
+ On versioned hosts, the existing `Read.Preconditions` policy must provide
163
+ `prepare(paths, session)`. It captures immutable read bases for that invocation
164
+ and returns `read(path)` and `commit(changes)` operations. `read` must return
165
+ bytes matching the captured base, or refuse; edits compute only from those bytes. Each handler submits one complete
166
+ batch of writes and removals; a move includes both its destination write and
167
+ source removal. The provider must compare every captured base before applying
168
+ any mutation: a stale preflight leaves the whole batch unchanged. The production
169
+ coding provider follows ADR 0004 protocol 7: an application failure may retain a
170
+ durable prefix and requires fresh reads of every affected path. The host does
171
+ not issue compensating writes. Only a complete validated settlement advances
172
+ the ledger. Missing or malformed receipts and transport failures revoke read
173
+ authority even when the old bytes remain. Tool-internal reads never refresh the
174
+ model's read base.
175
+
176
+ A host semaphore keeps preparation and diagnostics ordered. It does not exclude
177
+ outside writers; that is the provider's responsibility. Versioned handlers create
178
+ no parent or lock directories before commit and never fall back to ordinary
179
+ filesystem writes. Missing providers fail with `provider_unavailable`. Diagnostics
180
+ are updated only after the complete batch succeeds. The production coding host
181
+ currently refuses mutations until its guest provider qualifies.
182
+
183
+ ## Write a whole file
184
+
185
+ `write` replaces a file, creating parent directories:
186
+
187
+ ```ts
188
+ import * as Write from "@smthrs/std/Write"
189
+
190
+ const written = Write.run({ path: "/workspace/notes.md", content: "# Notes\n" })
191
+ // written.bytesWritten, written.created
192
+ ```
193
+
194
+ It preserves the file's mode, and it refuses to write over a directory with
195
+ `command_failed`. Prefer `edit` for a targeted change: a whole-file write of a
196
+ file you only partly know is how an unrelated region disappears.
197
+
198
+ On ordinary filesystem hosts, `write`, `edit`, and `apply_patch` updates stage replacement bytes in a unique
199
+ sibling file, preserve existing permission bits and ownership, then rename it
200
+ over the destination. A failure before rename leaves the original bytes intact.
201
+ Existing symlinks continue to target the same file. Hard links to the old inode
202
+ keep its old contents. The host must support exclusive creation and atomic
203
+ rename; unsupported operations fail without falling back to truncation.
204
+
205
+ Temporary files are removed on failure and Effect interruption. Process death
206
+ can leave an unused temporary file. This is per-file atomicity, not a transaction
207
+ across a whole patch or a promise of persistence after power loss. No `fsync` is
208
+ performed. Timestamps and extended metadata such as ACLs are not copied.
209
+
210
+ ## Apply a patch instead
211
+
212
+ `apply_patch` accepts Codex's V4A patch text as one string, so a model trained on
213
+ that tool can use the shape it knows:
214
+
215
+ ```ts
216
+ import * as ApplyPatch from "@smthrs/std/ApplyPatch"
217
+
218
+ const result = ApplyPatch.run({
219
+ input: [
220
+ "*** Begin Patch",
221
+ "*** Update File: src/widen.ts",
222
+ "@@",
223
+ "- return value * 2",
224
+ "+ return value * 3",
225
+ "*** End Patch"
226
+ ].join("\n")
227
+ })
228
+ // result.added, result.modified, result.deleted, result.output
229
+ ```
230
+
231
+ One rule to know: a patch naming the same file in two sections is refused whole
232
+ rather than applied by halves. Every update hunk is derived from the file as it
233
+ is on disk, so the second section would start from an original the first has
234
+ already replaced. A file needing several changes carries several `@@` chunks
235
+ inside one section.
236
+
237
+ Because a patch names its files inside its own text, `apply_patch` cannot narrow
238
+ its effect envelope for one call, and declares the workspace-wide worst case.
239
+ `edit` narrows to the one path it was given, so prefer `edit` where a scheduler
240
+ is running calls concurrently.
@@ -0,0 +1,215 @@
1
+ ---
2
+ title: "Run a shell command"
3
+ description: "Send a command line or a script that needs no quoting, route it into a container, declare a hermetic envelope, and read the exit code, the bounded output, and the invalid-probe flag."
4
+ sidebar:
5
+ order: 4
6
+ ---
7
+
8
+ `bash` runs one command. It takes two shapes, and the difference is where the
9
+ payload is parsed.
10
+
11
+ ## A command line
12
+
13
+ ```ts
14
+ import * as Bash from "@smthrs/std/Bash"
15
+
16
+ const result = Bash.run({
17
+ mode: "unhermetic",
18
+ command: "pnpm vitest run src/widen.test.ts",
19
+ cwd: "/workspace",
20
+ timeoutMs: 120_000
21
+ })
22
+ ```
23
+
24
+ The line goes to the platform shell exactly as written, and it carries its own
25
+ arguments.
26
+
27
+ ## A script, delivered as data
28
+
29
+ ```ts
30
+ const result = Bash.run({
31
+ mode: "unhermetic",
32
+ interpreter: "python3",
33
+ script: "import sys\nprint(sys.argv[1:])\n",
34
+ args: ["alpha", "beta"],
35
+ cwd: "/workspace"
36
+ })
37
+ ```
38
+
39
+ `script` is program text delivered to the interpreter on standard input. Nothing
40
+ quotes it, escapes it, or terminates it with a heredoc marker, so the class of
41
+ failure that eats a quote out of
42
+ `docker exec c bash -lc '...python - <<EOF...'` cannot happen. `args` reach the
43
+ script as arguments rather than as interpolated text.
44
+
45
+ `interpreter` defaults to `bash`. `bash`, `zsh`, `sh`, and `dash` are told to
46
+ read the program with `-s`; `python` and `python3` with `-`; `node`, `ruby`,
47
+ `perl`, and anything else are given no file, which is how they read a program
48
+ from standard input.
49
+
50
+ Six input combinations are refused with `invalid_input`, each naming the fix:
51
+ `command` with `script`, neither of the two, `script` with `stdin`, `command`
52
+ with `args`, `command` with `interpreter`, and a hermetic containerised call.
53
+
54
+ ## Declare the environment
55
+
56
+ Host commands inherit a bootstrap allowlist, not the whole Smithers process
57
+ environment: `PATH`, `HOME`, `USER`, `LANG`, every `LC_*` locale variable,
58
+ `TERM`, `TMPDIR`, and `SHELL`. Add a variable to `env` when the command needs
59
+ it. Caller-declared names are applied last, including credential-shaped names,
60
+ so declaring one is an explicit decision to make its value readable by the
61
+ command. Undeclared provider keys and tokens are withheld.
62
+
63
+ Containerised commands receive the `env` entries through the container
64
+ transport; their remaining environment belongs to the container image. The
65
+ Docker and Podman transport supplies each value to the host child as
66
+ `SMITHERS_CONTAINER_ENV_KEY`, passes `-e SMITHERS_CONTAINER_ENV_KEY`, and renames
67
+ it to `KEY` inside the container with `sh -c`, so the container needs `sh`. A
68
+ requested `PATH` or `LD_PRELOAD` therefore never configures the host `docker`
69
+ process. An `env` name that is not a POSIX shell name is `invalid_input`. Timeout errors show the logical command without
70
+ container transport arguments.
71
+
72
+ ## Route it into a container
73
+
74
+ ```ts
75
+ const result = Bash.run({
76
+ mode: "unhermetic",
77
+ container: "testbed",
78
+ command: "python -m pytest tests/test_admin.py",
79
+ cwd: "/testbed"
80
+ })
81
+ ```
82
+
83
+ `container` names a container the host knows how to reach, and the `Container`
84
+ service turns the request into the argv the host spawns. `Container.layerCommand`
85
+ builds the `docker exec` form, which `podman` shares.
86
+
87
+ The native CLI refuses named-container execution with `provider_unavailable`.
88
+ An existing Docker daemon is outside its OS sandbox. Isolated providers are
89
+ tracked in [#1790](https://github.com/smithersai/smithers/issues/1790).
90
+
91
+ The transport always goes through a login shell, because the images an agent
92
+ meets activate the project's interpreter from `/etc/profile.d`. A program
93
+ spawned directly by `docker exec` gets a different Python from the one that owns
94
+ the repository's dependencies.
95
+
96
+ A host that binds no transport refuses the call with `provider_unavailable` and
97
+ a message telling the caller to drop the `container` field. That is the honest
98
+ answer: this host has no container route.
99
+
100
+ ## Declare a hermetic envelope
101
+
102
+ `mode: "hermetic"` requires explicit `reads` and `writes`, and the handler
103
+ checks the command's explicit path tokens against them before spawning:
104
+
105
+ ```ts
106
+ const result = Bash.run({
107
+ mode: "hermetic",
108
+ command: "cp /workspace/src/a.ts /workspace/build/a.ts",
109
+ reads: ["/workspace/src/**"],
110
+ writes: ["/workspace/build/**"]
111
+ })
112
+ ```
113
+
114
+ A token outside the declaration fails with `outside_declared_reads` or
115
+ `outside_declared_writes` before anything runs, and the narrowed envelope makes
116
+ the call `compensable` instead of `irreversible`, so a scheduler can run it
117
+ beside work that touches other paths.
118
+
119
+ Read [Hermetic mode is a pre-check, not a sandbox](../concepts/effects-and-capabilities.md#hermetic-mode-is-a-pre-check-not-a-sandbox)
120
+ before you rely on this. The check is lexical: it bounds what the caller
121
+ declared it would do, not what the process can do.
122
+
123
+ ## Confine approved commands
124
+
125
+ The CLI and native flow hosts use bubblewrap on Linux and seatbelt on macOS.
126
+ Approval to start a command does not open filesystem writes or networking.
127
+ The host derives those permissions from its effective grants, including the
128
+ current capability ceiling. A missing sandbox refuses the command.
129
+
130
+ Matching `fs:read:/workspace/build/**`, `fs:write:/workspace/build`, and
131
+ `fs:write:/workspace/build/**` grants open the `build` tree for writing.
132
+ The directory entry needs its own write authority. Literal writes,
133
+ complex globs, and permissions narrowed by a deny stay closed when the native
134
+ mechanism cannot represent them safely. Egress opens only with unrestricted
135
+ `net:get`, `net:post`, and `net:private` grants. Host-specific network grants
136
+ keep networking closed. Host Unix sockets stay closed with open IP networking,
137
+ except the fixed macOS system DNS resolver endpoint. Commands also receive private temporary storage.
138
+
139
+ `NodeHost` and `BunHost` supply confinement. A custom native host provides
140
+ [`ProcessConfinement.layer()`](/api/platform-node#processconfinement) to the
141
+ kernel spawner. A missing confinement service refuses execution.
142
+ `mode: "hermetic"` continues to check declarations before execution; it does
143
+ not grant additional OS access.
144
+
145
+ ## Read the result
146
+
147
+ A non-zero exit code is an ordinary value, not a failure. Only a timeout, a
148
+ spawn failure, a permission refusal, and the hermetic pre-check use the error
149
+ channel.
150
+
151
+ | Field | Meaning |
152
+ | ------------------------------------------ | ----------------------------------------------------------- |
153
+ | `exitCode` | The command's exit code. |
154
+ | `stdout`, `stderr` | The captured streams, tail-first when truncated. |
155
+ | `stdoutTruncated`, `stderrTruncated` | Whether that stream is a fragment. |
156
+ | `stdoutDroppedBytes`, `stderrDroppedBytes` | Bytes omitted from the start. |
157
+ | `invalidProbe` | Present when the shell refused to start the command at all. |
158
+
159
+ Each stream is bounded at 30,000 bytes and the tail is kept, because a failing
160
+ command prints its verdict last. Never write a truncated stream to a file: it is
161
+ the end of a log, not the content it came from. `@smthrs/harness` reads the
162
+ `Truncated` flags to refuse exactly that.
163
+
164
+ `timeoutMs` defaults to `Bash.DEFAULT_TIMEOUT_MS`, ten minutes.
165
+
166
+ ## The invalid-probe flag
167
+
168
+ A non-zero exit is a runner's verdict about the code it ran. It is not a verdict
169
+ about the command it was handed. When a command names a test, a file, a module,
170
+ an environment, or a program that does not exist, the runner never reaches any
171
+ code and still exits non-zero.
172
+
173
+ `invalidProbe` names that case, with a `reason` from a closed list
174
+ (`unknown-command`, `unknown-test`, `unknown-path`, `unknown-module`,
175
+ `unknown-environment`), the `evidence` it rests on, and a `message` stating
176
+ what the result does and does not prove.
177
+
178
+ ```ts
179
+ if (result.invalidProbe !== undefined) {
180
+ // The exit code is about the command. Fix the names and run it again
181
+ // before drawing any conclusion from it.
182
+ }
183
+ ```
184
+
185
+ `bash` does not infer a launch failure from exit code 126 or 127: a launched
186
+ runner can return either status after running a check. It returns the captured
187
+ command result without `invalidProbe` when launch cannot be established. The
188
+ `test` flow asks the attribution judge whether a non-zero exit describes the
189
+ code under test or an unresolved name. See
190
+ [Run the test suite](./run-the-test-suite.md#who-the-failure-belongs-to).
191
+
192
+ ## The Codex-shaped alternative
193
+
194
+ `shell_command` is a clone of the Codex CLI tool of the same name, for a model
195
+ trained on that shape. It takes `command`, `workdir`, and `timeout_ms`, and it
196
+ returns Codex's own rendering:
197
+
198
+ ```ts
199
+ import * as ShellCommand from "@smthrs/std/ShellCommand"
200
+
201
+ const result = ShellCommand.run({ command: "ls -la", workdir: "/workspace" })
202
+ // result.output: "Exit code: 0\nWall time: 0.1 seconds\nOutput:\n..."
203
+ // result.exitCode: 124 when the command timed out
204
+ ```
205
+
206
+ The timeout defaults to 10 seconds, not ten minutes, and a timeout is a
207
+ successful value with exit code `ShellCommand.TIMEOUT_EXIT_CODE`. Output is
208
+ shaped to a 10,000-token budget by truncating the middle rather than the head.
209
+ Codex's `sandbox_permissions`, `justification`, and `prefix_rule` approval
210
+ parameters are deliberately absent: the permission kernel owns sandboxing and
211
+ escalation here.
212
+
213
+ Prefer `bash` for new work. It carries the effect envelope, the container
214
+ transport, the script form, and the per-stream truncation fields that
215
+ `shell_command` does not.
@@ -0,0 +1,154 @@
1
+ ---
2
+ title: "Run the test suite and attribute a failure"
3
+ description: "Declare how the project under test runs its suite, select what to run, and use against:'base' to separate the failures your edit introduced from the ones that were already there."
4
+ sidebar:
5
+ order: 5
6
+ ---
7
+
8
+ The `test` flow answers three questions a shell command cannot: what the suite
9
+ reported, which of the failures are yours, and whether the run failed about the
10
+ code at all.
11
+
12
+ ## Declare the runner once
13
+
14
+ A caller of `test` selects **which** tests, never **how** to run them. The
15
+ invocation is a host declaration, bound through the `TestRunner` service:
16
+
17
+ ```ts
18
+ import * as TestRunner from "@smthrs/std/TestRunner"
19
+
20
+ const runner = TestRunner.layer({
21
+ command: "python -m pytest -q",
22
+ cwd: "/testbed",
23
+ root: "/workspace/repo",
24
+ container: "testbed",
25
+ env: { PYTHONDONTWRITEBYTECODE: "1" },
26
+ timeoutMs: 900_000
27
+ })
28
+ ```
29
+
30
+ | Field | Meaning |
31
+ | ----------- | -------------------------------------------------------------------- |
32
+ | `command` | The runner command line, with no test selection in it. |
33
+ | `cwd` | Where the runner runs. The container's path when `container` is set. |
34
+ | `root` | The host path of the git repository, when it differs from `cwd`. |
35
+ | `container` | A container to route the run through, via the `Container` transport. |
36
+ | `env` | Environment the runner needs. |
37
+ | `baseRef` | The ref whose commit is the pristine base. |
38
+ | `timeoutMs` | Default wall-clock budget for one run. |
39
+
40
+ `cwd` and `root` differ exactly when the runner runs in a container: the
41
+ container sees the repository at `cwd`, the host sees it at `root`, and a
42
+ baseline checkout created at `<root>/.flows-test-base/run-<lease>` is visible to the runner
43
+ at `<cwd>/.flows-test-base/run-<lease>`, because it is one directory under two names.
44
+
45
+ A host with no runner binds `TestRunner.layerNoop`. The flow then fails with
46
+ `provider_unavailable` and tells the caller to use `bash` with the command the
47
+ project's own documentation gives.
48
+
49
+ ## Run a selection
50
+
51
+ ```ts
52
+ import * as TestRun from "@smthrs/std/TestRun"
53
+
54
+ const result = TestRun.run({
55
+ selection: ["tests/test_admin.py::AdminViewBasicTest::test_change_list"]
56
+ })
57
+ ```
58
+
59
+ Selection entries reach the runner as arguments, never as text spliced into the
60
+ command line. The invocation is `bash -lc '<command> "$@"' <command> id...`, so a
61
+ test id holding `::`, `[`, `]`, spaces, or shell metacharacters stays data.
62
+ Omitting `selection` runs everything.
63
+
64
+ The result is a reading, not a log:
65
+
66
+ | Field | Meaning |
67
+ | ----------------------------------- | -------------------------------------------------------------------------- |
68
+ | `command` | The logical invocation, without container transport arguments. |
69
+ | `exitCode` | The runner's exit code. |
70
+ | `passed` | Tests reported passing. Zero when `parsed` is false. |
71
+ | `failed` | Ids of the tests reported failing or erroring. |
72
+ | `parsed` | Whether the runner's complete report could be read. |
73
+ | `tail` | The end of the runner's combined output. |
74
+ | `tailTruncated`, `tailDroppedBytes` | Whether `tail` is a fragment, and by how much. |
75
+ | `invalidProbe` | Present when the exit code describes the command, not the code under test. |
76
+
77
+ When `parsed` is false, `tail` is all there is, and base attribution is omitted
78
+ rather than guessed at.
79
+
80
+ Unittest skips and expected failures, and TAP skips and TODO failures, do not
81
+ count as passing or failing tests. A successful TAP TODO counts as passing.
82
+ Unittest unexpected successes count as failures; attribution requires their
83
+ reported ids. Python 3.10 class-only headers and Python 3.11+ full test ids are
84
+ both supported. Missing failure ids or unknown unittest summary fields leave
85
+ `parsed` false.
86
+
87
+ ## Who the failure belongs to
88
+
89
+ A non-zero exit is a runner's verdict about the code it ran, not about the
90
+ command it was handed. A run that names a test, a file, a module, an
91
+ environment, or a program that does not exist never reaches any code and still
92
+ exits non-zero, so it reads the same before and after a correct fix.
93
+ `invalidProbe` is present when this run was one of those, with a `reason` from
94
+ that closed list and a `message` saying what the result does and does not
95
+ prove.
96
+
97
+ Jev makes that attribution. The flow asks the `probe/attribution` classifier
98
+ through the `Evaluator` service of [`@smthrs/model`](/api/model), so a host
99
+ binds an evaluator on a subscription seat. Only a zero exit is attributed without a judge. Exit codes 126 and 127
100
+ also go through attribution: a runner can return them after executing tests.
101
+ A judge that cannot
102
+ be reached, refuses, times out, or answers something unusable fails the call
103
+ with `provider_unavailable`, `timeout`, or `request_failed`, because a guess at
104
+ whether a reproduction reproduced is worth less than no answer at all.
105
+
106
+ ## Attribute a failure to your own edit
107
+
108
+ The native CLI supports workspace tests. Baseline comparison refuses before any
109
+ command starts; isolated staging is tracked in
110
+ [#3234](https://github.com/smithersai/smithers/issues/3234). A host declares this
111
+ with `baseline: false`.
112
+
113
+ `against: "base"` runs the same selection a second time against the pristine
114
+ base commit, in a scratch checkout, and differences the two failure sets:
115
+
116
+ ```ts
117
+ const result = TestRun.run({
118
+ selection: ["tests/test_admin.py"],
119
+ against: "base"
120
+ })
121
+
122
+ result.introduced // failing here and not on the base tree: yours
123
+ result.preexisting // failing on both: not yours, and not worth investigating
124
+ result.fixed // failing on the base tree and passing here
125
+ result.base // the base run's own outcome, plus its ref and commit
126
+ ```
127
+
128
+ That is the whole of attribution, in one call. Without it, the same question
129
+ costs a revert of the very work it was meant to prove.
130
+
131
+ The baseline commit is resolved from the runner's `baseRef`, then from
132
+ `TestRunner.captureBase` (`refs/flows/capture-base`), then from `HEAD`. A
133
+ `baseRef` that does not resolve is an error rather than a fallback, because a
134
+ baseline against the wrong tree answers the attribution question wrong.
135
+
136
+ The baseline is a detached checkout at `<root>/.flows-test-base/run-<lease>`, under
137
+ `TestRun.scratchDirectory`. Each call gets a unique lease. Existing checkouts
138
+ are left alone; a `SIGKILL` can leave one behind. Inside the repository is the only place that works:
139
+ a runner reaching the repository through a container mount sees a scratch
140
+ checkout anywhere else on the host as a path that does not exist. It is removed
141
+ when the call ends, however it ends. It is written from a temporary shadow
142
+ `GIT_DIR`, like a checkpoint, so no hook or filter driver in the workspace's
143
+ `.git` runs on the host and the repository's format is never changed.
144
+
145
+ `against: "base"` needs a repository directory. A runner declaring neither `root`
146
+ nor `cwd` fails with `invalid_input`.
147
+
148
+ ## Bound the run
149
+
150
+ `timeoutMs` on the call overrides the runner's own, which overrides
151
+ `TestRun.DEFAULT_TIMEOUT_MS` (ten minutes). The run holds at most
152
+ `TestRun.MAX_CAPTURE_BYTES` of output in memory, and `tail` carries the last
153
+ 30,000 bytes of it, so `tail` holds the part of a long run that says what
154
+ failed. A timeout is a `timeout` failure, not a result.