@vibe-agent-toolkit/utils 0.1.42 → 0.2.0-rc.10

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 (279) hide show
  1. package/README.md +81 -19
  2. package/dist/asset-reference.js +3 -11
  3. package/dist/asset-reference.js.map +1 -1
  4. package/dist/compare-code-units.d.ts +28 -0
  5. package/dist/compare-code-units.d.ts.map +1 -0
  6. package/dist/compare-code-units.js +33 -0
  7. package/dist/compare-code-units.js.map +1 -0
  8. package/dist/crawl-timing.d.ts +657 -0
  9. package/dist/crawl-timing.d.ts.map +1 -0
  10. package/dist/crawl-timing.js +765 -0
  11. package/dist/crawl-timing.js.map +1 -0
  12. package/dist/crawl.d.ts +2 -4
  13. package/dist/crawl.d.ts.map +1 -1
  14. package/dist/crawl.js +2 -4
  15. package/dist/crawl.js.map +1 -1
  16. package/dist/dirent-kind.d.ts +83 -0
  17. package/dist/dirent-kind.d.ts.map +1 -0
  18. package/dist/dirent-kind.js +129 -0
  19. package/dist/dirent-kind.js.map +1 -0
  20. package/dist/entrypoint.d.ts +54 -0
  21. package/dist/entrypoint.d.ts.map +1 -0
  22. package/dist/entrypoint.js +71 -0
  23. package/dist/entrypoint.js.map +1 -0
  24. package/dist/env-flag.d.ts +51 -0
  25. package/dist/env-flag.d.ts.map +1 -0
  26. package/dist/env-flag.js +62 -0
  27. package/dist/env-flag.js.map +1 -0
  28. package/dist/errors/errno.d.ts +51 -0
  29. package/dist/errors/errno.d.ts.map +1 -0
  30. package/dist/errors/errno.js +112 -0
  31. package/dist/errors/errno.js.map +1 -0
  32. package/dist/errors/vat-error.d.ts +60 -0
  33. package/dist/errors/vat-error.d.ts.map +1 -0
  34. package/dist/errors/vat-error.js +86 -0
  35. package/dist/errors/vat-error.js.map +1 -0
  36. package/dist/file-crawler.d.ts +60 -0
  37. package/dist/file-crawler.d.ts.map +1 -1
  38. package/dist/file-crawler.js +214 -24
  39. package/dist/file-crawler.js.map +1 -1
  40. package/dist/fs/file-hash.d.ts.map +1 -1
  41. package/dist/fs/file-hash.js +0 -1
  42. package/dist/fs/file-hash.js.map +1 -1
  43. package/dist/fs-utils.d.ts +628 -38
  44. package/dist/fs-utils.d.ts.map +1 -1
  45. package/dist/fs-utils.js +770 -71
  46. package/dist/fs-utils.js.map +1 -1
  47. package/dist/fs.d.ts +5 -1
  48. package/dist/fs.d.ts.map +1 -1
  49. package/dist/fs.js +9 -1
  50. package/dist/fs.js.map +1 -1
  51. package/dist/git-root-cache.d.ts +44 -0
  52. package/dist/git-root-cache.d.ts.map +1 -0
  53. package/dist/git-root-cache.js +68 -0
  54. package/dist/git-root-cache.js.map +1 -0
  55. package/dist/git-run.d.ts +167 -0
  56. package/dist/git-run.d.ts.map +1 -0
  57. package/dist/git-run.js +154 -0
  58. package/dist/git-run.js.map +1 -0
  59. package/dist/git-snapshot.d.ts +199 -0
  60. package/dist/git-snapshot.d.ts.map +1 -0
  61. package/dist/git-snapshot.js +250 -0
  62. package/dist/git-snapshot.js.map +1 -0
  63. package/dist/git-tracker.d.ts +166 -3
  64. package/dist/git-tracker.d.ts.map +1 -1
  65. package/dist/git-tracker.js +250 -22
  66. package/dist/git-tracker.js.map +1 -1
  67. package/dist/git-utils.d.ts +95 -1
  68. package/dist/git-utils.d.ts.map +1 -1
  69. package/dist/git-utils.js +227 -81
  70. package/dist/git-utils.js.map +1 -1
  71. package/dist/git.d.ts +13 -4
  72. package/dist/git.d.ts.map +1 -1
  73. package/dist/git.js +12 -4
  74. package/dist/git.js.map +1 -1
  75. package/dist/gitignore-checker.d.ts.map +1 -1
  76. package/dist/gitignore-checker.js +15 -6
  77. package/dist/gitignore-checker.js.map +1 -1
  78. package/dist/glob/glob-pattern.js +5 -5
  79. package/dist/glob/glob-pattern.js.map +1 -1
  80. package/dist/index.d.ts +33 -19
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +113 -33
  83. package/dist/index.js.map +1 -1
  84. package/dist/listing-refusal.d.ts +112 -0
  85. package/dist/listing-refusal.d.ts.map +1 -0
  86. package/dist/listing-refusal.js +105 -0
  87. package/dist/listing-refusal.js.map +1 -0
  88. package/dist/numeric-args.d.ts +24 -0
  89. package/dist/numeric-args.d.ts.map +1 -0
  90. package/dist/numeric-args.js +37 -0
  91. package/dist/numeric-args.js.map +1 -0
  92. package/dist/path-containment.d.ts +64 -0
  93. package/dist/path-containment.d.ts.map +1 -0
  94. package/dist/path-containment.js +111 -0
  95. package/dist/path-containment.js.map +1 -0
  96. package/dist/path-core.d.ts +143 -18
  97. package/dist/path-core.d.ts.map +1 -1
  98. package/dist/path-core.js +171 -23
  99. package/dist/path-core.js.map +1 -1
  100. package/dist/path-utils.d.ts.map +1 -1
  101. package/dist/path-utils.js +42 -47
  102. package/dist/path-utils.js.map +1 -1
  103. package/dist/path.d.ts +1 -1
  104. package/dist/path.d.ts.map +1 -1
  105. package/dist/path.js +1 -1
  106. package/dist/path.js.map +1 -1
  107. package/dist/process.d.ts +7 -0
  108. package/dist/process.d.ts.map +1 -1
  109. package/dist/process.js +7 -0
  110. package/dist/process.js.map +1 -1
  111. package/dist/project-utils.d.ts +7 -1
  112. package/dist/project-utils.d.ts.map +1 -1
  113. package/dist/project-utils.js +24 -10
  114. package/dist/project-utils.js.map +1 -1
  115. package/dist/project.d.ts +7 -5
  116. package/dist/project.d.ts.map +1 -1
  117. package/dist/project.js +7 -5
  118. package/dist/project.js.map +1 -1
  119. package/dist/safe-exec.d.ts +40 -11
  120. package/dist/safe-exec.d.ts.map +1 -1
  121. package/dist/safe-exec.js +111 -25
  122. package/dist/safe-exec.js.map +1 -1
  123. package/dist/skill-targets.d.ts +2 -2
  124. package/dist/skill-targets.js +2 -2
  125. package/dist/skill-test/auth-resolver.d.ts +10 -2
  126. package/dist/skill-test/auth-resolver.d.ts.map +1 -1
  127. package/dist/skill-test/auth-resolver.js +26 -11
  128. package/dist/skill-test/auth-resolver.js.map +1 -1
  129. package/dist/skill-test/index.d.ts +1 -1
  130. package/dist/skill-test/index.d.ts.map +1 -1
  131. package/dist/skill-test/index.js +1 -1
  132. package/dist/skill-test/index.js.map +1 -1
  133. package/dist/skill-test/spawn-claude.d.ts +30 -1
  134. package/dist/skill-test/spawn-claude.d.ts.map +1 -1
  135. package/dist/skill-test/spawn-claude.js +71 -5
  136. package/dist/skill-test/spawn-claude.js.map +1 -1
  137. package/dist/skill-test/transcript.d.ts +41 -2
  138. package/dist/skill-test/transcript.d.ts.map +1 -1
  139. package/dist/skill-test/transcript.js +55 -10
  140. package/dist/skill-test/transcript.js.map +1 -1
  141. package/dist/spawn-hardened.js +0 -1
  142. package/dist/spawn-hardened.js.map +1 -1
  143. package/dist/stdio-blocking.js +13 -14
  144. package/dist/stdio-blocking.js.map +1 -1
  145. package/dist/test-helpers.d.ts +130 -79
  146. package/dist/test-helpers.d.ts.map +1 -1
  147. package/dist/test-helpers.js +229 -124
  148. package/dist/test-helpers.js.map +1 -1
  149. package/dist/testing/executables.d.ts +32 -0
  150. package/dist/testing/executables.d.ts.map +1 -0
  151. package/dist/testing/executables.js +70 -0
  152. package/dist/testing/executables.js.map +1 -0
  153. package/dist/testing/hostile-tree.d.ts +79 -0
  154. package/dist/testing/hostile-tree.d.ts.map +1 -0
  155. package/dist/testing/hostile-tree.js +164 -0
  156. package/dist/testing/hostile-tree.js.map +1 -0
  157. package/dist/testing/platform-gates.d.ts +31 -0
  158. package/dist/testing/platform-gates.d.ts.map +1 -0
  159. package/dist/testing/platform-gates.js +31 -0
  160. package/dist/testing/platform-gates.js.map +1 -0
  161. package/dist/testing/temp-dir.d.ts +255 -0
  162. package/dist/testing/temp-dir.d.ts.map +1 -0
  163. package/dist/testing/temp-dir.js +363 -0
  164. package/dist/testing/temp-dir.js.map +1 -0
  165. package/dist/testing.d.ts +94 -3
  166. package/dist/testing.d.ts.map +1 -1
  167. package/dist/testing.js +119 -3
  168. package/dist/testing.js.map +1 -1
  169. package/dist/text-content.d.ts +197 -0
  170. package/dist/text-content.d.ts.map +1 -0
  171. package/dist/text-content.js +354 -0
  172. package/dist/text-content.js.map +1 -0
  173. package/dist/text-file.d.ts +45 -0
  174. package/dist/text-file.d.ts.map +1 -0
  175. package/dist/text-file.js +51 -0
  176. package/dist/text-file.js.map +1 -0
  177. package/dist/text.d.ts +16 -0
  178. package/dist/text.d.ts.map +1 -0
  179. package/dist/text.js +16 -0
  180. package/dist/text.js.map +1 -0
  181. package/dist/timing-dump.d.ts +136 -0
  182. package/dist/timing-dump.d.ts.map +1 -0
  183. package/dist/timing-dump.js +229 -0
  184. package/dist/timing-dump.js.map +1 -0
  185. package/dist/windows-shell.d.ts +0 -1
  186. package/dist/windows-shell.d.ts.map +1 -1
  187. package/dist/windows-shell.js +0 -1
  188. package/dist/windows-shell.js.map +1 -1
  189. package/dist/zod-introspection.js +2 -2
  190. package/dist/zod-introspection.js.map +1 -1
  191. package/eslint/README.md +224 -50
  192. package/eslint/index.cjs +111 -97
  193. package/eslint/index.d.cts +16 -6
  194. package/eslint/rules/callee-name.cjs +23 -0
  195. package/eslint/rules/commands-import-boundary.cjs +148 -0
  196. package/eslint/rules/dead-import.cjs +62 -12
  197. package/eslint/rules/dirent-type-needs-symlink-check.cjs +282 -0
  198. package/eslint/rules/eslint-rule-factory.cjs +21 -3
  199. package/eslint/rules/exempt-path-matcher.cjs +2 -1
  200. package/eslint/rules/explicit-zod-strictness.cjs +120 -0
  201. package/eslint/rules/no-bare-dynamic-import-path.cjs +5 -1
  202. package/eslint/rules/no-bare-executable-spawn.cjs +70 -0
  203. package/eslint/rules/no-bare-symlink-in-tests.cjs +213 -0
  204. package/eslint/rules/no-blind-catch.cjs +171 -0
  205. package/eslint/rules/no-child-process-execSync.cjs +8 -0
  206. package/eslint/rules/no-decaying-referent.cjs +217 -0
  207. package/eslint/rules/no-dotdot-containment.cjs +160 -0
  208. package/eslint/rules/no-file-url-string-concat.cjs +4 -1
  209. package/eslint/rules/no-fragile-entrypoint-guard.cjs +228 -0
  210. package/eslint/rules/no-fs-mkdirSync.cjs +8 -0
  211. package/eslint/rules/no-fs-promises-cp.cjs +7 -0
  212. package/eslint/rules/no-fs-realpathSync.cjs +8 -0
  213. package/eslint/rules/no-hardcoded-path-split.cjs +29 -18
  214. package/eslint/rules/no-io-in-unit-tier.cjs +129 -0
  215. package/eslint/rules/no-literal-process-exit.cjs +129 -0
  216. package/eslint/rules/no-manual-path-normalize.cjs +146 -96
  217. package/eslint/rules/no-os-tmpdir.cjs +8 -0
  218. package/eslint/rules/no-path-operations-in-comparisons.cjs +7 -2
  219. package/eslint/rules/no-path-sep-in-strings.cjs +7 -2
  220. package/eslint/rules/no-path-startswith.cjs +7 -2
  221. package/eslint/rules/no-process-exit-in-phase.cjs +127 -0
  222. package/eslint/rules/no-raw-node-path.cjs +563 -0
  223. package/eslint/rules/no-raw-text-decode.cjs +305 -0
  224. package/eslint/rules/no-registry-count-pin.cjs +255 -0
  225. package/eslint/rules/no-self-package-import.cjs +168 -0
  226. package/eslint/rules/no-test-scoped-functions.cjs +10 -3
  227. package/eslint/rules/no-unix-shell-commands.cjs +6 -2
  228. package/eslint/rules/no-unsafe-root-join.cjs +23 -2
  229. package/eslint/rules/no-url-pathname-for-fs.cjs +5 -1
  230. package/eslint/rules/no-version-literal.cjs +151 -0
  231. package/eslint/rules/prefer-startswith-over-regex.cjs +33 -1
  232. package/eslint/rules/require-justified-skip.cjs +8 -2
  233. package/eslint/rules/safe-import.cjs +1 -1
  234. package/package.json +16 -16
  235. package/dist/link-auth/build-headers.d.ts +0 -34
  236. package/dist/link-auth/build-headers.d.ts.map +0 -1
  237. package/dist/link-auth/build-headers.js +0 -58
  238. package/dist/link-auth/build-headers.js.map +0 -1
  239. package/dist/link-auth/expand-macro.d.ts +0 -38
  240. package/dist/link-auth/expand-macro.d.ts.map +0 -1
  241. package/dist/link-auth/expand-macro.js +0 -133
  242. package/dist/link-auth/expand-macro.js.map +0 -1
  243. package/dist/link-auth/macros.yaml +0 -50
  244. package/dist/link-auth/resolve-token.d.ts +0 -83
  245. package/dist/link-auth/resolve-token.d.ts.map +0 -1
  246. package/dist/link-auth/resolve-token.js +0 -101
  247. package/dist/link-auth/resolve-token.js.map +0 -1
  248. package/dist/link-auth/resolve.d.ts +0 -102
  249. package/dist/link-auth/resolve.d.ts.map +0 -1
  250. package/dist/link-auth/resolve.js +0 -66
  251. package/dist/link-auth/resolve.js.map +0 -1
  252. package/dist/link-auth/rewrite.d.ts +0 -52
  253. package/dist/link-auth/rewrite.d.ts.map +0 -1
  254. package/dist/link-auth/rewrite.js +0 -102
  255. package/dist/link-auth/rewrite.js.map +0 -1
  256. package/dist/link-auth/select-provider.d.ts +0 -30
  257. package/dist/link-auth/select-provider.d.ts.map +0 -1
  258. package/dist/link-auth/select-provider.js +0 -55
  259. package/dist/link-auth/select-provider.js.map +0 -1
  260. package/dist/link-auth/template.d.ts +0 -40
  261. package/dist/link-auth/template.d.ts.map +0 -1
  262. package/dist/link-auth/template.js +0 -89
  263. package/dist/link-auth/template.js.map +0 -1
  264. package/dist/link-auth/transforms.d.ts +0 -46
  265. package/dist/link-auth/transforms.d.ts.map +0 -1
  266. package/dist/link-auth/transforms.js +0 -52
  267. package/dist/link-auth/transforms.js.map +0 -1
  268. package/dist/template-entry.d.ts +0 -10
  269. package/dist/template-entry.d.ts.map +0 -1
  270. package/dist/template-entry.js +0 -10
  271. package/dist/template-entry.js.map +0 -1
  272. package/dist/template.d.ts +0 -7
  273. package/dist/template.d.ts.map +0 -1
  274. package/dist/template.js +0 -18
  275. package/dist/template.js.map +0 -1
  276. package/eslint/rules/no-path-join.cjs +0 -14
  277. package/eslint/rules/no-path-relative.cjs +0 -14
  278. package/eslint/rules/no-path-resolve.cjs +0 -14
  279. package/eslint/rules/path-function-rule-factory.cjs +0 -417
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore-checker.js","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,MAAuB,MAAM,QAAQ,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAG,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,OAAgB;IAClE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,+BAA+B;IAC/B,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACf,QAAQ,GAAG,IAAI,CAAC;IAEhB,kDAAkD;IAClD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAElD,+CAA+C;IAC/C,MAAM,iBAAiB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;IAE1D,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAChE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAChC,IAAI,UAAU,KAAK,eAAe,EAAE,CAAC;YACnC,MAAM;QACR,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,sDAAsD;IACtD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACvD,qHAAqH;QACrH,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,sFAAsF;gBACtF,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;gBACxD,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAClB,CAAC;YAAC,MAAM,CAAC;gBACP,qCAAqC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"gitignore-checker.js","sourceRoot":"","sources":["../src/gitignore-checker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,MAAuB,MAAM,QAAQ,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAG,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,OAAgB;IAClE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,+BAA+B;IAC/B,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACf,QAAQ,GAAG,IAAI,CAAC;IAEhB,kDAAkD;IAClD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAElD,+CAA+C;IAC/C,MAAM,iBAAiB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;IAE1D,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAChE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAChC,IAAI,UAAU,KAAK,eAAe,EAAE,CAAC;YACnC,MAAM;QACR,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,sDAAsD;IACtD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACvD,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,wEAAwE;gBACxE,oEAAoE;gBACpE,yEAAyE;gBACzE,qBAAqB;gBACrB,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC;YAClD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,wEAAwE;gBACxE,gEAAgE;gBAChE,wEAAwE;gBACxE,kEAAkE;gBAClE,+CAA+C;gBAC/C,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;oBAAE,MAAM,KAAK,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9B,CAAC"}
@@ -11,7 +11,7 @@
11
11
  * sets an `escaped` flag when it sees `\`; the *next* character is skipped for
12
12
  * magic detection if `escaped` is true.
13
13
  */
14
- import { toForwardSlash } from '../path-core.js';
14
+ import { toForwardSlashAnyPlatform } from '../path-core.js';
15
15
  /** The glob metacharacters recognised by this module. */
16
16
  const MAGIC_CHARS = new Set(['*', '?', '[']);
17
17
  /** Sentinel returned by {@link staticGlobBase} when the first segment is magic. */
@@ -69,9 +69,9 @@ export function isGlob(source) {
69
69
  * staticGlobBase('foo/bar.txt') // 'foo/bar.txt'
70
70
  */
71
71
  export function staticGlobBase(pattern) {
72
- // Glob patterns are always forward-slash; toForwardSlash() satisfies the
73
- // no-hardcoded-path-split lint rule while being a no-op in practice.
74
- const normalized = toForwardSlash(pattern);
72
+ // A glob is author-written text: a Windows-spelled separator reads as `/` on
73
+ // every host, whatever platform VAT runs on.
74
+ const normalized = toForwardSlashAnyPlatform(pattern);
75
75
  const segments = normalized.split('/');
76
76
  const staticSegments = [];
77
77
  for (const segment of segments) {
@@ -112,7 +112,7 @@ export function staticGlobBase(pattern) {
112
112
  * globMagicRemainder('../mycli/dist/*.mjs') // '*.mjs'
113
113
  */
114
114
  export function globMagicRemainder(pattern) {
115
- const forward = toForwardSlash(pattern);
115
+ const forward = toForwardSlashAnyPlatform(pattern);
116
116
  const base = staticGlobBase(pattern);
117
117
  if (base === DOT) {
118
118
  // First segment was magic — the remainder is the full (forward-slash) pattern.
@@ -1 +1 @@
1
- {"version":3,"file":"glob-pattern.js","sourceRoot":"","sources":["../../src/glob/glob-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,yDAAyD;AACzD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE7C,mFAAmF;AACnF,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,yEAAyE;IACzE,qEAAqE;IACrE,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACpB,MAAM;QACR,CAAC;QACD,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,cAAc,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9C,oEAAoE;QACpE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,uEAAuE;QACvE,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,gDAAgD;QAChD,OAAO,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,+EAA+E;QAC/E,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,yDAAyD;QACzD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,yEAAyE;QACzE,yEAAyE;QACzE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,wDAAwD;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"glob-pattern.js","sourceRoot":"","sources":["../../src/glob/glob-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,yDAAyD;AACzD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAE7C,mFAAmF;AACnF,MAAM,GAAG,GAAG,GAAG,CAAC;AAEhB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,6EAA6E;IAC7E,6CAA6C;IAC7C,MAAM,UAAU,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACpB,MAAM;QACR,CAAC;QACD,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,cAAc,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9C,oEAAoE;QACpE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,uEAAuE;QACvE,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,gDAAgD;QAChD,OAAO,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,OAAO,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,+EAA+E;QAC/E,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,yDAAyD;QACzD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,yEAAyE;QACzE,yEAAyE;QACzE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,wDAAwD;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,31 +3,45 @@
3
3
  * Core shared utilities with no dependencies on other packages
4
4
  *
5
5
  * Utilities are added as needed by other packages, not speculatively.
6
+ *
7
+ * **A module that brings a third-party dependency belongs on a subpath, not
8
+ * here.** This entry has ~245 in-repo importers plus published adopters, and
9
+ * every one of them pays for the whole graph reachable from it — a bundler that
10
+ * cannot tree-shake a dependency (a CJS package, or one reached through
11
+ * `new URL(..., import.meta.url)`) inlines it into every consumer that touched
12
+ * a path helper. The domains that carry weight each have their own entry:
13
+ * `./crawl`, `./git`, `./process`, `./skill-test`, `./template`, `./yaml`.
14
+ * `./skill-test` is there for a *transitive* reason rather than a direct one —
15
+ * it declares no dependency itself, but spawning a headless agent goes through
16
+ * `./process`, which reaches `which` and (because `safeExecSync` refuses `git`
17
+ * and delegates) `@vibe-validate/git`. Reachability is the criterion, not the
18
+ * import a module happens to write.
19
+ *
20
+ * The rule is enforced, not merely stated: `test/subpath-purity.test.ts` asserts
21
+ * this entry's reachable third-party set by equality, so a dependency arriving
22
+ * here — directly or transitively, through any module below — turns that row red
23
+ * and has to be an argued edit rather than an unnoticed one.
6
24
  */
7
- export * from './safe-exec.js';
8
- export * from './windows-shell.js';
9
- export * from './spawn-hardened.js';
25
+ export * from './errors/vat-error.js';
10
26
  export * from './path-utils.js';
11
- export * from './stdio-blocking.js';
27
+ export * from './path-containment.js';
28
+ export * from './dirent-kind.js';
29
+ export * from './text-content.js';
30
+ export * from './text-file.js';
12
31
  export * from './asset-reference.js';
13
- export * from './fs-utils.js';
14
- export * from './file-crawler.js';
15
- export * from './gitignore-checker.js';
16
- export * from './git-url.js';
17
- export * from './git-utils.js';
32
+ export { isFilesystemAccessError, isPathAbsentError } from './errors/errno.js';
33
+ export { copyDirectory, CopyLinkEscapesSourceError, FsLookupCache, transientRefusalClause, } from './fs-utils.js';
34
+ export { DirectorySpellingIndex, fillPathSpellings, fillRealpaths, pathSpellingFrom, realpathFrom, spellingWalkRoot, } from './fs-utils.js';
35
+ export type { AbsenceCause, ComponentMatch, FilenameMatch, PathProbe, PathProbeStats, PathSpelling, PathSpellingRequest, PathSpellingTable, RealpathTable, VerifiedPrefix, } from './fs-utils.js';
18
36
  export * from './project-utils.js';
19
- export * from './git-tracker.js';
20
- export * from './test-helpers.js';
37
+ export { createSymlink, createSymlinkAsync, detachGitEnv, errnoError, INHERITED_GIT_ENV, symlinkCapability, type SymlinkCapability, } from './test-helpers.js';
21
38
  export * from './zod-introspection.js';
22
- export * from './template.js';
23
39
  export * from './skill-targets.js';
24
- export { type LinkAuthConfig, type Provider, type ProviderAuth, type ProviderCheck, resolveAuthenticatedUrl, type ResolveOutcome, } from './link-auth/resolve.js';
25
- export type { ProviderMatch } from './link-auth/select-provider.js';
26
- export type { RewriteRule } from './link-auth/rewrite.js';
27
- export { defaultRunCommand, type TokenSource } from './link-auth/resolve-token.js';
28
- export { expandMacro, UnknownMacroError } from './link-auth/expand-macro.js';
29
- export * from './skill-test/index.js';
30
40
  export * from './glob/glob-pattern.js';
31
41
  export * from './fs/file-hash.js';
32
- export * from './yaml/surgical-yaml.js';
42
+ export { parseWholeNumberAtLeast } from './numeric-args.js';
43
+ export { parseEnvBoolean } from './env-flag.js';
44
+ export { compareCodeUnits } from './compare-code-units.js';
45
+ export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADMIT_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, type CrawlDriverStratum, type CrawlStratum, type CrawlTimingDump, type CrawlTimingEntry, type CrawlTimingProcess, } from './crawl-timing.js';
46
+ export { ensureTimingDirectory, normalizeTimingDirectory, readTimingProcess, type TimingProcess, writeTimingDump, } from './timing-dump.js';
33
47
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAI/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,cAAc,uBAAuB,CAAC;AAGtC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,kBAAkB,CAAC;AASjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,sBAAsB,CAAC;AAyCrC,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,aAAa,EACb,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,SAAS,EACT,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,eAAe,CAAC;AAIvB,cAAc,oBAAoB,CAAC;AASnC,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,cAAc,wBAAwB,CAAC;AAGvC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAK5D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgB3D,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,aAAa,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -3,53 +3,133 @@
3
3
  * Core shared utilities with no dependencies on other packages
4
4
  *
5
5
  * Utilities are added as needed by other packages, not speculatively.
6
+ *
7
+ * **A module that brings a third-party dependency belongs on a subpath, not
8
+ * here.** This entry has ~245 in-repo importers plus published adopters, and
9
+ * every one of them pays for the whole graph reachable from it — a bundler that
10
+ * cannot tree-shake a dependency (a CJS package, or one reached through
11
+ * `new URL(..., import.meta.url)`) inlines it into every consumer that touched
12
+ * a path helper. The domains that carry weight each have their own entry:
13
+ * `./crawl`, `./git`, `./process`, `./skill-test`, `./template`, `./yaml`.
14
+ * `./skill-test` is there for a *transitive* reason rather than a direct one —
15
+ * it declares no dependency itself, but spawning a headless agent goes through
16
+ * `./process`, which reaches `which` and (because `safeExecSync` refuses `git`
17
+ * and delegates) `@vibe-validate/git`. Reachability is the criterion, not the
18
+ * import a module happens to write.
19
+ *
20
+ * The rule is enforced, not merely stated: `test/subpath-purity.test.ts` asserts
21
+ * this entry's reachable third-party set by equality, so a dependency arriving
22
+ * here — directly or transitively, through any module below — turns that row red
23
+ * and has to be an argued edit rather than an unnoticed one.
6
24
  */
7
- // Safe command execution (cross-platform, no shell injection)
8
- export * from './safe-exec.js';
9
- // Windows shell-invocation helpers (.cmd/.bat/.ps1 handling), shared by every spawn wrapper
10
- export * from './windows-shell.js';
11
- // Hardened async spawn (streaming stdio + correct Windows .cmd/.bat launching)
12
- export * from './spawn-hardened.js';
25
+ // The base of every error VAT throws on purpose; `code` is what a catch
26
+ // block dispatches on, never `message`.
27
+ export * from './errors/vat-error.js';
13
28
  // Cross-platform path utilities
14
29
  export * from './path-utils.js';
15
- // Blocking stdio for published bins (process.exit must not truncate output)
16
- export * from './stdio-blocking.js';
30
+ // The filesystem-backed containment verdict every delete/copy/uninstall sink asks.
31
+ export * from './path-containment.js';
32
+ // The Dirent classifiers a walk uses instead of a bare isFile()/isDirectory().
33
+ export * from './dirent-kind.js';
34
+ // THE content-decoding seam: bytes to text, in one place. `decodeTextContent` is
35
+ // pure and also reachable from the dependency-free `./text` entry; the two
36
+ // file-reading wrappers need `node:fs` and are also on `./fs`. Other routes from
37
+ // bytes to text — `buf.toString('utf-8')`, `new TextDecoder()`,
38
+ // `readFile(p, 'utf-8')` — are a lint error under `local/no-raw-text-decode`
39
+ // WHERE IT IS REGISTERED (this package's `src` and `resources`' `src`); the rest
40
+ // of the repo is a migration ledger in `eslint.config.js`, not a covered claim.
41
+ export * from './text-content.js';
42
+ export * from './text-file.js';
17
43
  // Asset reference resolution (paths + npm bare specifiers)
18
44
  export * from './asset-reference.js';
19
- // Filesystem utilities
20
- export * from './fs-utils.js';
21
- // Directory crawling with glob patterns
22
- export * from './file-crawler.js';
23
- // Git ignore checking
24
- export * from './gitignore-checker.js';
25
- // Git URL parsing (parse/detect git URLs, GitHub shorthand, SSH forms)
26
- export * from './git-url.js';
27
- // Git utilities (using git commands directly)
28
- export * from './git-utils.js';
45
+ // Filesystem utilities.
46
+ //
47
+ // Named rather than `export *` on purpose: `fs-utils.ts` holds internal members
48
+ // of the fill+judge pairs below — the per-directory index build, the table-key
49
+ // derivation — and a star re-export would publish each of them on this barrel
50
+ // the moment it was written. (The `./fs` subpath was already an explicit list
51
+ // and was never at risk.) The public surface is a decision, not a side effect of
52
+ // module layout.
53
+ //
54
+ // TWO materialized columns are published, both shaped fill-first-then-judge:
55
+ //
56
+ // - path spellings — `fillPathSpellings` plus `pathSpellingFrom`. It judges a
57
+ // WHOLE path, which is what a caller validating references needs: judging
58
+ // only the basename hands every directory component back to the host
59
+ // filesystem's own folding, so a link that resolves on macOS 404s on a
60
+ // case-sensitive filesystem. The `DirectorySpellingIndex` underneath is
61
+ // published too, for the lazy caller that cannot enumerate its targets up
62
+ // front.
63
+ // - realpaths — `fillRealpaths` (every canonicalization, once, up front) plus
64
+ // `realpathFrom`.
65
+ //
66
+ // In both, the row lookup IS the judge: the row is the answer, so there is
67
+ // nothing left to keep internal.
68
+ //
69
+ // There is deliberately no one-call wrapper composing either pair: handed one, a
70
+ // caller with many paths loops over it, which reinstates the per-path `await` the
71
+ // pairs exist to remove.
72
+ //
73
+ // `PathSpellingTable` and `RealpathTable` — what the fills return and the judges
74
+ // consume — are the types a caller can name, as are `PathSpelling`,
75
+ // `PathSpellingRequest`, `ComponentMatch` and `FilenameMatch`, which a consumer
76
+ // receives and branches on.
77
+ //
78
+ // The cost of that decision, stated so it is not a surprise: a new *type* added
79
+ // to `fs-utils.ts` no longer reaches consumers automatically, and
80
+ // `barrel-exports.test.ts` pins runtime names only, so nothing will fail. The
81
+ // symptom is a type that cannot be imported, which surfaces the first time
82
+ // someone tries — not a silent break in existing code.
83
+ // The lookups themselves, plus the memo every fill shares.
84
+ export { isFilesystemAccessError, isPathAbsentError } from './errors/errno.js';
85
+ export { copyDirectory, CopyLinkEscapesSourceError, FsLookupCache, transientRefusalClause, } from './fs-utils.js';
86
+ // The two fill+judge pairs, in the order the note above lists them, plus the
87
+ // lazy index a caller that cannot enumerate its targets up front reaches for.
88
+ export { DirectorySpellingIndex, fillPathSpellings, fillRealpaths, pathSpellingFrom, realpathFrom, spellingWalkRoot, } from './fs-utils.js';
29
89
  // Project root discovery (canonical: config → git → null).
30
90
  // CLI-boundary use only — see docs/concepts/roots-and-config.md.
31
91
  export * from './project-utils.js';
32
- // Git tracking cache (for efficient git-ignore checking)
33
- export * from './git-tracker.js';
34
- // Test helpers for isolated test output directories
35
- export * from './test-helpers.js';
92
+ // The runtime half of `test-helpers.ts`: symlink creation with its host
93
+ // capability probe, and the git-environment detachment every child process
94
+ // needs. Named rather than `export *` because the SAME module also holds the
95
+ // fs-refusal fakes (`refuseSyncFs` and siblings), which are test scaffolding
96
+ // and reach adopters on the `./testing` subpath only. A published runtime
97
+ // barrel that carried them — eight such names, once — was the audit's finding,
98
+ // and an `export *` here is how they got in.
99
+ export { createSymlink, createSymlinkAsync, detachGitEnv, errnoError, INHERITED_GIT_ENV, symlinkCapability, } from './test-helpers.js';
36
100
  // Zod type introspection (version-agnostic)
37
101
  export * from './zod-introspection.js';
38
- // Handlebars template rendering (cached, no HTML escaping)
39
- export * from './template.js';
40
102
  // Skill target resolution (cross-platform flat skill install paths)
41
103
  export * from './skill-targets.js';
42
- // linkAuth pure engine — public API only (issue #113).
43
- // Internal helpers (rewrite, build-headers, etc.) stay module-private.
44
- export { resolveAuthenticatedUrl, } from './link-auth/resolve.js';
45
- export { defaultRunCommand } from './link-auth/resolve-token.js';
46
- export { expandMacro, UnknownMacroError } from './link-auth/expand-macro.js';
47
- // Skill testing utilities (environment management for headless agent runs)
48
- export * from './skill-test/index.js';
49
104
  // Glob pattern helpers (isGlob, staticGlobBase, globMagicRemainder)
50
105
  export * from './glob/glob-pattern.js';
51
106
  // Filesystem hashing (sha256 of raw file bytes)
52
107
  export * from './fs/file-hash.js';
53
- // Byte-surgical YAML value updater (replace/insert without reflowing the doc)
54
- export * from './yaml/surgical-yaml.js';
108
+ export { parseWholeNumberAtLeast } from './numeric-args.js';
109
+ // THE reading of an environment variable as a boolean. One implementation
110
+ // because three switches each had their own `!== '0'` comparison and none of
111
+ // them turned off for `=false`.
112
+ export { parseEnvBoolean } from './env-flag.js';
113
+ // Machine-independent string ordering for hashed/serialized output — never `localeCompare`.
114
+ export { compareCodeUnits } from './compare-code-units.js';
115
+ // The crawl-timing seam: which contributor, stratum and fixpoint pass owns the
116
+ // time it takes to FIND documents.
117
+ //
118
+ // It lives HERE, at the bottom of the graph, because the work it measures is
119
+ // spread across four packages above this one — `resources` builds the registry,
120
+ // `agent-skills` walks the link graph, `claude-marketplace` enumerates an
121
+ // inventory, and `utils` itself initializes the `GitTracker` both crawlers
122
+ // consume. Both arms must record through ONE recorder or the two are not
123
+ // comparable, and only `utils` is beneath all of them. See the module header.
124
+ //
125
+ // Named rather than `export *`: the accumulator internals (`addEntry`,
126
+ // `keyOf`, `recordInheritedPass`) are not surface, and `timing-dump.ts` is
127
+ // plumbing shared with `resources`' package-internal `parse-timing.ts` — a star
128
+ // re-export would publish both the moment either grew a symbol.
129
+ export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADMIT_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, } from './crawl-timing.js';
130
+ // The three `__*ForTest` seams of the same module are on `./testing`, not here.
131
+ // The on-disk plumbing both timing seams share. Exported because
132
+ // `resources`' `parse-timing.ts` is the other consumer and now sits a package
133
+ // away; nothing else should reach for it.
134
+ export { ensureTimingDirectory, normalizeTimingDirectory, readTimingProcess, writeTimingDump, } from './timing-dump.js';
55
135
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,4FAA4F;AAC5F,cAAc,oBAAoB,CAAC;AAEnC,+EAA+E;AAC/E,cAAc,qBAAqB,CAAC;AAEpC,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,4EAA4E;AAC5E,cAAc,qBAAqB,CAAC;AAEpC,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,uEAAuE;AACvE,cAAc,cAAc,CAAC;AAE7B,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,yDAAyD;AACzD,cAAc,kBAAkB,CAAC;AAEjC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,2DAA2D;AAC3D,cAAc,eAAe,CAAC;AAE9B,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,uDAAuD;AACvD,uEAAuE;AACvE,OAAO,EAKL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,2EAA2E;AAC3E,cAAc,uBAAuB,CAAC;AAEtC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wEAAwE;AACxE,wCAAwC;AACxC,cAAc,uBAAuB,CAAC;AAEtC,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAChC,mFAAmF;AACnF,cAAc,uBAAuB,CAAC;AACtC,+EAA+E;AAC/E,cAAc,kBAAkB,CAAC;AAEjC,iFAAiF;AACjF,2EAA2E;AAC3E,iFAAiF;AACjF,gEAAgE;AAChE,6EAA6E;AAC7E,iFAAiF;AACjF,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,wBAAwB;AACxB,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,iFAAiF;AACjF,iBAAiB;AACjB,EAAE;AACF,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAC9E,aAAa;AACb,gFAAgF;AAChF,sBAAsB;AACtB,EAAE;AACF,2EAA2E;AAC3E,iCAAiC;AACjC,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,yBAAyB;AACzB,EAAE;AACF,iFAAiF;AACjF,oEAAoE;AACpE,gFAAgF;AAChF,4BAA4B;AAC5B,EAAE;AACF,gFAAgF;AAChF,kEAAkE;AAClE,8EAA8E;AAC9E,2EAA2E;AAC3E,uDAAuD;AACvD,2DAA2D;AAC3D,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,aAAa,EACb,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,6EAA6E;AAC7E,8EAA8E;AAC9E,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAcvB,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,wEAAwE;AACxE,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,+EAA+E;AAC/E,6CAA6C;AAC7C,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,mBAAmB,CAAC;AAE3B,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,0EAA0E;AAC1E,6EAA6E;AAC7E,gCAAgC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,4FAA4F;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,+EAA+E;AAC/E,mCAAmC;AACnC,EAAE;AACF,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,2EAA2E;AAC3E,yEAAyE;AACzE,8EAA8E;AAC9E,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,gFAAgF;AAChF,gEAAgE;AAChE,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,GAMjB,MAAM,mBAAmB,CAAC;AAC3B,gFAAgF;AAEhF,iEAAiE;AACjE,8EAA8E;AAC9E,0CAA0C;AAC1C,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EAEjB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * What a listing does with a directory it was refused — the vocabulary shared
3
+ * by the filesystem walk (`file-crawler.ts`) and the git listings
4
+ * (`git-utils.ts`), so a caller decides ONCE for both routes.
5
+ *
6
+ * 🚨 A refused listing is a gap in the POPULATION: every file beneath that
7
+ * directory the listing would have found was never seen and is absent from
8
+ * every count downstream. There are exactly two honest answers — stop, with a
9
+ * sentence the adopter can act on, or keep going and REPORT the gap — and
10
+ * which one is right is the caller's knowledge, not the crawler's. So the
11
+ * policy is {@link UnreadablePolicy}, it is REQUIRED wherever a listing is
12
+ * asked for, and it has no default.
13
+ *
14
+ * 🪤 It used to be `onUnreadable?`, an optional callback. Every caller that
15
+ * ignored it compiled; the two routes then defaulted differently (the walk
16
+ * threw a programmer-facing sentence, the git route dropped the refusal off
17
+ * its stderr without a word); and the miss surfaced one review round later as
18
+ * a HIGH. A required field is what makes `tsc` enumerate the callers.
19
+ */
20
+ import { VatError } from './errors/vat-error.js';
21
+ import { type DirectoryRefusal } from './fs-utils.js';
22
+ /**
23
+ * What a caller that STOPS on a refusal tells the person reading the error.
24
+ *
25
+ * A caller that has decided to stop — a build that must not ship an incomplete
26
+ * bundle, a discovery that must not silently find fewer skills — owes the
27
+ * adopter the directory against the root they know, and the knob THEY have.
28
+ */
29
+ export interface RefuseListingContext {
30
+ /**
31
+ * The root the refused directory is expressed against. An absolute path in
32
+ * an error is the developer's `$HOME` in every CI log.
33
+ */
34
+ root: string;
35
+ /**
36
+ * What the adopter can do about it — naming this lane's deliberate-drop
37
+ * mechanism (`resources.exclude`, a plugin `exclude:`, `--exclude`), which
38
+ * differs per caller and is why the crawler cannot supply it.
39
+ */
40
+ remedy: string;
41
+ }
42
+ /**
43
+ * The caller's decision about a directory the listing cannot open.
44
+ *
45
+ * - `{ refuse }` — STOP: the listing throws {@link DirectoryListingRefusedError}
46
+ * with the adopter-facing sentence built from the context. Right for every
47
+ * lane whose output is acted on as a complete population (a build, a
48
+ * discovery, a fingerprint, a copy).
49
+ * - `{ degrade }` — KEEP GOING and hand the refusal over. The caller is
50
+ * promising to REPORT the gap — as its own finding, with the directory and
51
+ * errno the refusal carries — not to drop it. Right for a backstop appended
52
+ * to a larger report, where one unlistable directory must not destroy every
53
+ * finding beside it.
54
+ *
55
+ * A directory that VANISHED between being enumerated and being listed
56
+ * (`ENOENT` / `ENOTDIR`) is not a refusal under either arm: it is no longer in
57
+ * the population and is skipped without a call.
58
+ */
59
+ export type UnreadablePolicy = {
60
+ readonly refuse: RefuseListingContext;
61
+ } | {
62
+ readonly degrade: (refusal: DirectoryRefusal) => void;
63
+ };
64
+ /**
65
+ * Thrown by a listing under `{ refuse }` when a directory refused to be
66
+ * listed. The message is the adopter's sentence — see {@link refusedListingMessage}.
67
+ */
68
+ export declare class DirectoryListingRefusedError extends VatError {
69
+ readonly refusal: DirectoryRefusal;
70
+ constructor(refusal: DirectoryRefusal, context: RefuseListingContext);
71
+ }
72
+ /**
73
+ * The adopter-facing sentence: root-relative directory, errno, the gap, and
74
+ * the caller's remedy — **the one owner of that sentence.**
75
+ *
76
+ * Exported so every lane that refuses says the same thing. Three lanes used to
77
+ * compose this by hand and had drifted by a clause each ("enumerated" /
78
+ * "scanned" / "the population could not be enumerated"); the transient clause
79
+ * in particular was written once in `fs-utils.ts` precisely so nobody would.
80
+ * See {@link REFUSAL_GAP_CLAUSE} for why it asserts nothing about what WAS
81
+ * enumerated beneath the directory.
82
+ *
83
+ * @param refusal - What was refused
84
+ * @param context - The root to express it against, and what the adopter can do
85
+ * @returns One sentence, root-relative, never containing the absolute path
86
+ */
87
+ export declare function refusedListingMessage(refusal: DirectoryRefusal, context: RefuseListingContext): string;
88
+ /**
89
+ * Apply the caller's policy to one refusal: throw under `{ refuse }`, hand it
90
+ * over under `{ degrade }`. The single place either route settles a refusal,
91
+ * so the two cannot drift.
92
+ *
93
+ * @param policy - The caller's decision
94
+ * @param refusal - The directory that could not be listed
95
+ */
96
+ export declare function settleRefusal(policy: UnreadablePolicy, refusal: DirectoryRefusal): void;
97
+ /**
98
+ * Refuse an omitted policy up front, by name, before any directory is listed.
99
+ *
100
+ * The type already makes `unreadable` required, and that is what enumerates
101
+ * the TypeScript callers. This is the runtime half, for the callers the type
102
+ * cannot reach — test files are not typechecked by the build, and a JavaScript
103
+ * adopter has no compiler at all. Without it an omitted policy would surface
104
+ * only on the first refusal, as a `TypeError` from the `in` operator, and a
105
+ * tree with nothing unreadable would keep returning complete lists — the
106
+ * optional seam back again, one layer down.
107
+ *
108
+ * @param policy - What the caller passed as `unreadable`
109
+ * @param api - The entry point, for the sentence
110
+ */
111
+ export declare function requireUnreadablePolicy(policy: UnreadablePolicy | undefined, api: string): asserts policy is UnreadablePolicy;
112
+ //# sourceMappingURL=listing-refusal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listing-refusal.d.ts","sourceRoot":"","sources":["../src/listing-refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,eAAe,CAAC;AAG9E;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GACzC;IAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAAE,CAAC;AAE9D;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,QAAQ;IACxD,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBAEvB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,oBAAoB;CAIrE;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAOtG;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAGvF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,gBAAgB,CAO7H"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * What a listing does with a directory it was refused — the vocabulary shared
3
+ * by the filesystem walk (`file-crawler.ts`) and the git listings
4
+ * (`git-utils.ts`), so a caller decides ONCE for both routes.
5
+ *
6
+ * 🚨 A refused listing is a gap in the POPULATION: every file beneath that
7
+ * directory the listing would have found was never seen and is absent from
8
+ * every count downstream. There are exactly two honest answers — stop, with a
9
+ * sentence the adopter can act on, or keep going and REPORT the gap — and
10
+ * which one is right is the caller's knowledge, not the crawler's. So the
11
+ * policy is {@link UnreadablePolicy}, it is REQUIRED wherever a listing is
12
+ * asked for, and it has no default.
13
+ *
14
+ * 🪤 It used to be `onUnreadable?`, an optional callback. Every caller that
15
+ * ignored it compiled; the two routes then defaulted differently (the walk
16
+ * threw a programmer-facing sentence, the git route dropped the refusal off
17
+ * its stderr without a word); and the miss surfaced one review round later as
18
+ * a HIGH. A required field is what makes `tsc` enumerate the callers.
19
+ */
20
+ import { VatError } from './errors/vat-error.js';
21
+ import { transientRefusalClause } from './fs-utils.js';
22
+ import { safePath, toForwardSlash } from './path-utils.js';
23
+ /**
24
+ * Thrown by a listing under `{ refuse }` when a directory refused to be
25
+ * listed. The message is the adopter's sentence — see {@link refusedListingMessage}.
26
+ */
27
+ export class DirectoryListingRefusedError extends VatError {
28
+ refusal;
29
+ constructor(refusal, context) {
30
+ super('DIRECTORY_LISTING_REFUSED', refusedListingMessage(refusal, context));
31
+ this.refusal = refusal;
32
+ }
33
+ }
34
+ /**
35
+ * What a refused listing costs, said so it is true on BOTH routes.
36
+ *
37
+ * 🪤 It used to read "so nothing beneath it was enumerated: every file there
38
+ * is in the declared scan". Both halves were the readdir walk's truth and the
39
+ * git route's lie: `git ls-files --others` reports the refusal while the index
40
+ * has already named every TRACKED file beneath the directory — the same run
41
+ * that printed the sentence had scanned one of them — and the projection's
42
+ * population is the whole non-ignored tree, which no `include`/`exclude`
43
+ * "declared". What holds on every route is the hazard itself: whatever the
44
+ * listing would have found and nothing else named is missing, and the shorter
45
+ * result is indistinguishable from a complete one.
46
+ */
47
+ const REFUSAL_GAP_CLAUSE = 'any file beneath it that no other listing named is absent from every count, ' +
48
+ 'and the result cannot be told from a complete one';
49
+ /**
50
+ * The adopter-facing sentence: root-relative directory, errno, the gap, and
51
+ * the caller's remedy — **the one owner of that sentence.**
52
+ *
53
+ * Exported so every lane that refuses says the same thing. Three lanes used to
54
+ * compose this by hand and had drifted by a clause each ("enumerated" /
55
+ * "scanned" / "the population could not be enumerated"); the transient clause
56
+ * in particular was written once in `fs-utils.ts` precisely so nobody would.
57
+ * See {@link REFUSAL_GAP_CLAUSE} for why it asserts nothing about what WAS
58
+ * enumerated beneath the directory.
59
+ *
60
+ * @param refusal - What was refused
61
+ * @param context - The root to express it against, and what the adopter can do
62
+ * @returns One sentence, root-relative, never containing the absolute path
63
+ */
64
+ export function refusedListingMessage(refusal, context) {
65
+ const relative = toForwardSlash(safePath.relative(context.root, refusal.directory));
66
+ const where = relative === '' ? 'the scan root itself' : `the directory '${relative}'`;
67
+ const remedy = refusal.transient
68
+ ? `${transientRefusalClause(refusal.code)}, so nothing is wrong with the tree — re-run before investigating anything.`
69
+ : context.remedy;
70
+ return `Listing ${where} was refused (${refusal.code}): ${REFUSAL_GAP_CLAUSE}. ${remedy}`;
71
+ }
72
+ /**
73
+ * Apply the caller's policy to one refusal: throw under `{ refuse }`, hand it
74
+ * over under `{ degrade }`. The single place either route settles a refusal,
75
+ * so the two cannot drift.
76
+ *
77
+ * @param policy - The caller's decision
78
+ * @param refusal - The directory that could not be listed
79
+ */
80
+ export function settleRefusal(policy, refusal) {
81
+ if ('refuse' in policy)
82
+ throw new DirectoryListingRefusedError(refusal, policy.refuse);
83
+ policy.degrade(refusal);
84
+ }
85
+ /**
86
+ * Refuse an omitted policy up front, by name, before any directory is listed.
87
+ *
88
+ * The type already makes `unreadable` required, and that is what enumerates
89
+ * the TypeScript callers. This is the runtime half, for the callers the type
90
+ * cannot reach — test files are not typechecked by the build, and a JavaScript
91
+ * adopter has no compiler at all. Without it an omitted policy would surface
92
+ * only on the first refusal, as a `TypeError` from the `in` operator, and a
93
+ * tree with nothing unreadable would keep returning complete lists — the
94
+ * optional seam back again, one layer down.
95
+ *
96
+ * @param policy - What the caller passed as `unreadable`
97
+ * @param api - The entry point, for the sentence
98
+ */
99
+ export function requireUnreadablePolicy(policy, api) {
100
+ if (policy === undefined) {
101
+ throw new TypeError(`${api}: \`unreadable\` is required — pass { refuse: { root, remedy } } to stop on a directory the listing cannot open, ` +
102
+ 'or { degrade: (refusal) => … } to keep going and report the gap yourself.');
103
+ }
104
+ }
105
+ //# sourceMappingURL=listing-refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listing-refusal.js","sourceRoot":"","sources":["../src/listing-refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAyB,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA4C3D;;;GAGG;AACH,MAAM,OAAO,4BAA6B,SAAQ,QAAQ;IAC/C,OAAO,CAAmB;IAEnC,YAAY,OAAyB,EAAE,OAA6B;QAClE,KAAK,CAAC,2BAA2B,EAAE,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,kBAAkB,GACtB,8EAA8E;IAC9E,mDAAmD,CAAC;AAEtD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAyB,EAAE,OAA6B;IAC5F,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,kBAAkB,QAAQ,GAAG,CAAC;IACvF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS;QAC9B,CAAC,CAAC,GAAG,sBAAsB,CAAC,OAAO,CAAC,IAAI,CAAC,6EAA6E;QACtH,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACnB,OAAO,WAAW,KAAK,iBAAiB,OAAO,CAAC,IAAI,MAAM,kBAAkB,KAAK,MAAM,EAAE,CAAC;AAC5F,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,MAAwB,EAAE,OAAyB;IAC/E,IAAI,QAAQ,IAAI,MAAM;QAAE,MAAM,IAAI,4BAA4B,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAoC,EAAE,GAAW;IACvF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CACjB,GAAG,GAAG,mHAAmH;YACvH,2EAA2E,CAC9E,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Validation for numeric command-line arguments.
3
+ *
4
+ * Deliberately free of any CLI-framework types: the rule is "is this a whole
5
+ * number at or above a floor", which has nothing to do with Commander. Callers
6
+ * that need a framework-specific error catch this one and re-raise, which is
7
+ * what lets a CLI print a usage message while the rule itself stays testable
8
+ * without a parser.
9
+ */
10
+ /**
11
+ * Parse a whole number that must be at or above a floor.
12
+ *
13
+ * The error names the flag as the user spelled it, because "expects a whole
14
+ * number" without saying *which* option is a message that sends someone back to
15
+ * `--help` to guess.
16
+ *
17
+ * @param value - Raw string as typed on the command line
18
+ * @param floor - Smallest value that makes sense for this option
19
+ * @param flag - Flag spelling, used in the error message
20
+ * @returns The parsed number
21
+ * @throws Error when the value is not a whole number at or above the floor
22
+ */
23
+ export declare function parseWholeNumberAtLeast(value: string, floor: number, flag: string): number;
24
+ //# sourceMappingURL=numeric-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numeric-args.d.ts","sourceRoot":"","sources":["../src/numeric-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiB1F"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Validation for numeric command-line arguments.
3
+ *
4
+ * Deliberately free of any CLI-framework types: the rule is "is this a whole
5
+ * number at or above a floor", which has nothing to do with Commander. Callers
6
+ * that need a framework-specific error catch this one and re-raise, which is
7
+ * what lets a CLI print a usage message while the rule itself stays testable
8
+ * without a parser.
9
+ */
10
+ /**
11
+ * Parse a whole number that must be at or above a floor.
12
+ *
13
+ * The error names the flag as the user spelled it, because "expects a whole
14
+ * number" without saying *which* option is a message that sends someone back to
15
+ * `--help` to guess.
16
+ *
17
+ * @param value - Raw string as typed on the command line
18
+ * @param floor - Smallest value that makes sense for this option
19
+ * @param flag - Flag spelling, used in the error message
20
+ * @returns The parsed number
21
+ * @throws Error when the value is not a whole number at or above the floor
22
+ */
23
+ export function parseWholeNumberAtLeast(value, floor, flag) {
24
+ const invalid = new Error(`${flag} expects a whole number of at least ${String(floor)}; got '${value}'.`);
25
+ // Number() coercion accepts far more than decimal digits — '' -> 0,
26
+ // '0x10' -> 16, '1e21' -> a value Number.isInteger still calls whole.
27
+ // Require plain ASCII digits before ever calling Number() on it.
28
+ if (!/^\d+$/.test(value)) {
29
+ throw invalid;
30
+ }
31
+ const parsed = Number(value);
32
+ if (!Number.isInteger(parsed) || parsed < floor) {
33
+ throw invalid;
34
+ }
35
+ return parsed;
36
+ }
37
+ //# sourceMappingURL=numeric-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numeric-args.js","sourceRoot":"","sources":["../src/numeric-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,KAAa,EAAE,IAAY;IAChF,MAAM,OAAO,GAAG,IAAI,KAAK,CACvB,GAAG,IAAI,uCAAuC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI,CAC/E,CAAC;IAEF,oEAAoE;IACpE,sEAAsE;IACtE,iEAAiE;IACjE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,KAAK,EAAE,CAAC;QAChD,MAAM,OAAO,CAAC;IAChB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}