@vibe-agent-toolkit/cli 0.2.0-rc.10 → 0.2.0-rc.12

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 (755) hide show
  1. package/README.md +3 -3
  2. package/dist/bin/supervise-cli.d.ts +45 -0
  3. package/dist/bin/supervise-cli.d.ts.map +1 -0
  4. package/dist/bin/supervise-cli.js +83 -0
  5. package/dist/bin/supervise-cli.js.map +1 -0
  6. package/dist/bin/vat +94 -40
  7. package/dist/bin/vat.d.ts +15 -4
  8. package/dist/bin/vat.d.ts.map +1 -1
  9. package/dist/bin/vat.js +94 -40
  10. package/dist/bin/vat.js.map +1 -1
  11. package/dist/bin.js +21 -29
  12. package/dist/bin.js.map +1 -1
  13. package/dist/command-tree.d.ts +45 -0
  14. package/dist/command-tree.d.ts.map +1 -0
  15. package/dist/command-tree.js +60 -0
  16. package/dist/command-tree.js.map +1 -0
  17. package/dist/commands/agent/build-schema.d.ts +100 -0
  18. package/dist/commands/agent/build-schema.d.ts.map +1 -0
  19. package/dist/commands/agent/build-schema.js +32 -0
  20. package/dist/commands/agent/build-schema.js.map +1 -0
  21. package/dist/commands/agent/build.d.ts +1 -0
  22. package/dist/commands/agent/build.d.ts.map +1 -1
  23. package/dist/commands/agent/build.js +63 -33
  24. package/dist/commands/agent/build.js.map +1 -1
  25. package/dist/commands/agent/import-schema.d.ts +75 -0
  26. package/dist/commands/agent/import-schema.d.ts.map +1 -0
  27. package/dist/commands/agent/import-schema.js +25 -0
  28. package/dist/commands/agent/import-schema.js.map +1 -0
  29. package/dist/commands/agent/import.d.ts.map +1 -1
  30. package/dist/commands/agent/import.js +33 -27
  31. package/dist/commands/agent/import.js.map +1 -1
  32. package/dist/commands/agent/index.d.ts.map +1 -1
  33. package/dist/commands/agent/index.js +132 -37
  34. package/dist/commands/agent/index.js.map +1 -1
  35. package/dist/commands/agent/install-path.d.ts.map +1 -1
  36. package/dist/commands/agent/install-path.js +2 -1
  37. package/dist/commands/agent/install-path.js.map +1 -1
  38. package/dist/commands/agent/install-schema.d.ts +89 -0
  39. package/dist/commands/agent/install-schema.d.ts.map +1 -0
  40. package/dist/commands/agent/install-schema.js +29 -0
  41. package/dist/commands/agent/install-schema.js.map +1 -0
  42. package/dist/commands/agent/install.d.ts +7 -1
  43. package/dist/commands/agent/install.d.ts.map +1 -1
  44. package/dist/commands/agent/install.js +78 -108
  45. package/dist/commands/agent/install.js.map +1 -1
  46. package/dist/commands/agent/installed-schema.d.ts +140 -0
  47. package/dist/commands/agent/installed-schema.d.ts.map +1 -0
  48. package/dist/commands/agent/installed-schema.js +36 -0
  49. package/dist/commands/agent/installed-schema.js.map +1 -0
  50. package/dist/commands/agent/installed.d.ts +1 -1
  51. package/dist/commands/agent/installed.d.ts.map +1 -1
  52. package/dist/commands/agent/installed.js +104 -75
  53. package/dist/commands/agent/installed.js.map +1 -1
  54. package/dist/commands/agent/list-schema.d.ts +128 -0
  55. package/dist/commands/agent/list-schema.d.ts.map +1 -0
  56. package/dist/commands/agent/list-schema.js +34 -0
  57. package/dist/commands/agent/list-schema.js.map +1 -0
  58. package/dist/commands/agent/list.d.ts +4 -3
  59. package/dist/commands/agent/list.d.ts.map +1 -1
  60. package/dist/commands/agent/list.js +50 -37
  61. package/dist/commands/agent/list.js.map +1 -1
  62. package/dist/commands/agent/run.d.ts +3 -0
  63. package/dist/commands/agent/run.d.ts.map +1 -1
  64. package/dist/commands/agent/run.js +8 -3
  65. package/dist/commands/agent/run.js.map +1 -1
  66. package/dist/commands/agent/uninstall-schema.d.ts +89 -0
  67. package/dist/commands/agent/uninstall-schema.d.ts.map +1 -0
  68. package/dist/commands/agent/uninstall-schema.js +29 -0
  69. package/dist/commands/agent/uninstall-schema.js.map +1 -0
  70. package/dist/commands/agent/uninstall.d.ts +5 -1
  71. package/dist/commands/agent/uninstall.d.ts.map +1 -1
  72. package/dist/commands/agent/uninstall.js +50 -38
  73. package/dist/commands/agent/uninstall.js.map +1 -1
  74. package/dist/commands/agent/validate-schema.d.ts +129 -0
  75. package/dist/commands/agent/validate-schema.d.ts.map +1 -0
  76. package/dist/commands/agent/validate-schema.js +35 -0
  77. package/dist/commands/agent/validate-schema.js.map +1 -0
  78. package/dist/commands/agent/validate.d.ts +6 -0
  79. package/dist/commands/agent/validate.d.ts.map +1 -1
  80. package/dist/commands/agent/validate.js +64 -36
  81. package/dist/commands/agent/validate.js.map +1 -1
  82. package/dist/commands/ard/emit-schema.d.ts +108 -0
  83. package/dist/commands/ard/emit-schema.d.ts.map +1 -0
  84. package/dist/commands/ard/emit-schema.js +37 -0
  85. package/dist/commands/ard/emit-schema.js.map +1 -0
  86. package/dist/commands/ard/emit.d.ts +31 -63
  87. package/dist/commands/ard/emit.d.ts.map +1 -1
  88. package/dist/commands/ard/emit.js +124 -68
  89. package/dist/commands/ard/emit.js.map +1 -1
  90. package/dist/commands/ard/index.d.ts.map +1 -1
  91. package/dist/commands/ard/index.js +17 -10
  92. package/dist/commands/ard/index.js.map +1 -1
  93. package/dist/commands/audit/compat-lane-findings.d.ts +65 -0
  94. package/dist/commands/audit/compat-lane-findings.d.ts.map +1 -0
  95. package/dist/commands/audit/compat-lane-findings.js +72 -0
  96. package/dist/commands/audit/compat-lane-findings.js.map +1 -0
  97. package/dist/commands/audit/distributed-tree.d.ts +2 -2
  98. package/dist/commands/audit/distributed-tree.d.ts.map +1 -1
  99. package/dist/commands/audit/distributed-tree.js +23 -12
  100. package/dist/commands/audit/distributed-tree.js.map +1 -1
  101. package/dist/commands/audit/git-url-clone.d.ts +15 -7
  102. package/dist/commands/audit/git-url-clone.d.ts.map +1 -1
  103. package/dist/commands/audit/git-url-clone.js +85 -42
  104. package/dist/commands/audit/git-url-clone.js.map +1 -1
  105. package/dist/commands/audit/hierarchical-output.d.ts +28 -4
  106. package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
  107. package/dist/commands/audit/hierarchical-output.js +44 -27
  108. package/dist/commands/audit/hierarchical-output.js.map +1 -1
  109. package/dist/commands/audit/scan-population.d.ts.map +1 -1
  110. package/dist/commands/audit/scan-population.js +2 -1
  111. package/dist/commands/audit/scan-population.js.map +1 -1
  112. package/dist/commands/audit-schema.d.ts +1247 -0
  113. package/dist/commands/audit-schema.d.ts.map +1 -0
  114. package/dist/commands/audit-schema.js +139 -0
  115. package/dist/commands/audit-schema.js.map +1 -0
  116. package/dist/commands/audit-settings-schema.d.ts +417 -0
  117. package/dist/commands/audit-settings-schema.d.ts.map +1 -0
  118. package/dist/commands/audit-settings-schema.js +77 -0
  119. package/dist/commands/audit-settings-schema.js.map +1 -0
  120. package/dist/commands/audit-settings.d.ts +28 -9
  121. package/dist/commands/audit-settings.d.ts.map +1 -1
  122. package/dist/commands/audit-settings.js +215 -151
  123. package/dist/commands/audit-settings.js.map +1 -1
  124. package/dist/commands/audit.d.ts +72 -33
  125. package/dist/commands/audit.d.ts.map +1 -1
  126. package/dist/commands/audit.js +415 -397
  127. package/dist/commands/audit.js.map +1 -1
  128. package/dist/commands/build.d.ts +61 -4
  129. package/dist/commands/build.d.ts.map +1 -1
  130. package/dist/commands/build.js +176 -190
  131. package/dist/commands/build.js.map +1 -1
  132. package/dist/commands/cache/clear-schema.d.ts +111 -0
  133. package/dist/commands/cache/clear-schema.d.ts.map +1 -0
  134. package/dist/commands/cache/clear-schema.js +37 -0
  135. package/dist/commands/cache/clear-schema.js.map +1 -0
  136. package/dist/commands/cache/clear.d.ts +28 -26
  137. package/dist/commands/cache/clear.d.ts.map +1 -1
  138. package/dist/commands/cache/clear.js +108 -103
  139. package/dist/commands/cache/clear.js.map +1 -1
  140. package/dist/commands/cache/index.d.ts.map +1 -1
  141. package/dist/commands/cache/index.js +13 -7
  142. package/dist/commands/cache/index.js.map +1 -1
  143. package/dist/commands/claude/claude-config.d.ts +23 -6
  144. package/dist/commands/claude/claude-config.d.ts.map +1 -1
  145. package/dist/commands/claude/claude-config.js +29 -15
  146. package/dist/commands/claude/claude-config.js.map +1 -1
  147. package/dist/commands/claude/context.d.ts +87 -2
  148. package/dist/commands/claude/context.d.ts.map +1 -1
  149. package/dist/commands/claude/context.js +116 -57
  150. package/dist/commands/claude/context.js.map +1 -1
  151. package/dist/commands/claude/marketplace/changelog-utils.js +2 -2
  152. package/dist/commands/claude/marketplace/changelog-utils.js.map +1 -1
  153. package/dist/commands/claude/marketplace/git-publish.d.ts +14 -1
  154. package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
  155. package/dist/commands/claude/marketplace/git-publish.js +135 -68
  156. package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
  157. package/dist/commands/claude/marketplace/license-utils.d.ts +3 -5
  158. package/dist/commands/claude/marketplace/license-utils.d.ts.map +1 -1
  159. package/dist/commands/claude/marketplace/license-utils.js +16 -7
  160. package/dist/commands/claude/marketplace/license-utils.js.map +1 -1
  161. package/dist/commands/claude/marketplace/publish-schema.d.ts +137 -0
  162. package/dist/commands/claude/marketplace/publish-schema.d.ts.map +1 -0
  163. package/dist/commands/claude/marketplace/publish-schema.js +32 -0
  164. package/dist/commands/claude/marketplace/publish-schema.js.map +1 -0
  165. package/dist/commands/claude/marketplace/publish-tree.d.ts +6 -0
  166. package/dist/commands/claude/marketplace/publish-tree.d.ts.map +1 -1
  167. package/dist/commands/claude/marketplace/publish-tree.js +75 -17
  168. package/dist/commands/claude/marketplace/publish-tree.js.map +1 -1
  169. package/dist/commands/claude/marketplace/publish.d.ts +27 -0
  170. package/dist/commands/claude/marketplace/publish.d.ts.map +1 -1
  171. package/dist/commands/claude/marketplace/publish.js +84 -50
  172. package/dist/commands/claude/marketplace/publish.js.map +1 -1
  173. package/dist/commands/claude/marketplace/validate-schema.d.ts +362 -0
  174. package/dist/commands/claude/marketplace/validate-schema.d.ts.map +1 -0
  175. package/dist/commands/claude/marketplace/validate-schema.js +67 -0
  176. package/dist/commands/claude/marketplace/validate-schema.js.map +1 -0
  177. package/dist/commands/claude/marketplace/validate.d.ts +40 -53
  178. package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
  179. package/dist/commands/claude/marketplace/validate.js +358 -214
  180. package/dist/commands/claude/marketplace/validate.js.map +1 -1
  181. package/dist/commands/claude/org/api-keys.d.ts +3 -0
  182. package/dist/commands/claude/org/api-keys.d.ts.map +1 -1
  183. package/dist/commands/claude/org/api-keys.js +4 -5
  184. package/dist/commands/claude/org/api-keys.js.map +1 -1
  185. package/dist/commands/claude/org/code-analytics.js +1 -1
  186. package/dist/commands/claude/org/code-analytics.js.map +1 -1
  187. package/dist/commands/claude/org/cost.d.ts.map +1 -1
  188. package/dist/commands/claude/org/cost.js +11 -33
  189. package/dist/commands/claude/org/cost.js.map +1 -1
  190. package/dist/commands/claude/org/helpers.d.ts +40 -27
  191. package/dist/commands/claude/org/helpers.d.ts.map +1 -1
  192. package/dist/commands/claude/org/helpers.js +61 -66
  193. package/dist/commands/claude/org/helpers.js.map +1 -1
  194. package/dist/commands/claude/org/index.d.ts.map +1 -1
  195. package/dist/commands/claude/org/index.js +10 -4
  196. package/dist/commands/claude/org/index.js.map +1 -1
  197. package/dist/commands/claude/org/info.d.ts.map +1 -1
  198. package/dist/commands/claude/org/info.js +2 -3
  199. package/dist/commands/claude/org/info.js.map +1 -1
  200. package/dist/commands/claude/org/invites.d.ts +3 -0
  201. package/dist/commands/claude/org/invites.d.ts.map +1 -1
  202. package/dist/commands/claude/org/invites.js +5 -7
  203. package/dist/commands/claude/org/invites.js.map +1 -1
  204. package/dist/commands/claude/org/skills.d.ts +76 -21
  205. package/dist/commands/claude/org/skills.d.ts.map +1 -1
  206. package/dist/commands/claude/org/skills.js +273 -246
  207. package/dist/commands/claude/org/skills.js.map +1 -1
  208. package/dist/commands/claude/org/stubs-schema.d.ts +56 -0
  209. package/dist/commands/claude/org/stubs-schema.d.ts.map +1 -0
  210. package/dist/commands/claude/org/stubs-schema.js +23 -0
  211. package/dist/commands/claude/org/stubs-schema.js.map +1 -0
  212. package/dist/commands/claude/org/stubs.d.ts +8 -3
  213. package/dist/commands/claude/org/stubs.d.ts.map +1 -1
  214. package/dist/commands/claude/org/stubs.js +9 -9
  215. package/dist/commands/claude/org/stubs.js.map +1 -1
  216. package/dist/commands/claude/org/usage.d.ts.map +1 -1
  217. package/dist/commands/claude/org/usage.js +1 -2
  218. package/dist/commands/claude/org/usage.js.map +1 -1
  219. package/dist/commands/claude/org/users.d.ts +3 -0
  220. package/dist/commands/claude/org/users.d.ts.map +1 -1
  221. package/dist/commands/claude/org/users.js +6 -8
  222. package/dist/commands/claude/org/users.js.map +1 -1
  223. package/dist/commands/claude/org/workspaces.d.ts +3 -0
  224. package/dist/commands/claude/org/workspaces.d.ts.map +1 -1
  225. package/dist/commands/claude/org/workspaces.js +10 -15
  226. package/dist/commands/claude/org/workspaces.js.map +1 -1
  227. package/dist/commands/claude/plugin/build-schema.d.ts +642 -0
  228. package/dist/commands/claude/plugin/build-schema.d.ts.map +1 -0
  229. package/dist/commands/claude/plugin/build-schema.js +51 -0
  230. package/dist/commands/claude/plugin/build-schema.js.map +1 -0
  231. package/dist/commands/claude/plugin/build.d.ts +220 -45
  232. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  233. package/dist/commands/claude/plugin/build.js +466 -249
  234. package/dist/commands/claude/plugin/build.js.map +1 -1
  235. package/dist/commands/claude/plugin/helpers.d.ts +186 -24
  236. package/dist/commands/claude/plugin/helpers.d.ts.map +1 -1
  237. package/dist/commands/claude/plugin/helpers.js +110 -68
  238. package/dist/commands/claude/plugin/helpers.js.map +1 -1
  239. package/dist/commands/claude/plugin/install-schema.d.ts +144 -0
  240. package/dist/commands/claude/plugin/install-schema.d.ts.map +1 -0
  241. package/dist/commands/claude/plugin/install-schema.js +36 -0
  242. package/dist/commands/claude/plugin/install-schema.js.map +1 -0
  243. package/dist/commands/claude/plugin/install.d.ts +191 -11
  244. package/dist/commands/claude/plugin/install.d.ts.map +1 -1
  245. package/dist/commands/claude/plugin/install.js +688 -628
  246. package/dist/commands/claude/plugin/install.js.map +1 -1
  247. package/dist/commands/claude/plugin/kept-findings.d.ts +19 -0
  248. package/dist/commands/claude/plugin/kept-findings.d.ts.map +1 -0
  249. package/dist/commands/claude/plugin/kept-findings.js +24 -0
  250. package/dist/commands/claude/plugin/kept-findings.js.map +1 -0
  251. package/dist/commands/claude/plugin/list-schema.d.ts +223 -0
  252. package/dist/commands/claude/plugin/list-schema.d.ts.map +1 -0
  253. package/dist/commands/claude/plugin/list-schema.js +34 -0
  254. package/dist/commands/claude/plugin/list-schema.js.map +1 -0
  255. package/dist/commands/claude/plugin/list.d.ts +18 -0
  256. package/dist/commands/claude/plugin/list.d.ts.map +1 -1
  257. package/dist/commands/claude/plugin/list.js +53 -45
  258. package/dist/commands/claude/plugin/list.js.map +1 -1
  259. package/dist/commands/claude/plugin/npm-pack.d.ts +15 -0
  260. package/dist/commands/claude/plugin/npm-pack.d.ts.map +1 -0
  261. package/dist/commands/claude/plugin/npm-pack.js +39 -0
  262. package/dist/commands/claude/plugin/npm-pack.js.map +1 -0
  263. package/dist/commands/claude/plugin/plugin-changelog.d.ts +5 -1
  264. package/dist/commands/claude/plugin/plugin-changelog.d.ts.map +1 -1
  265. package/dist/commands/claude/plugin/plugin-changelog.js +9 -5
  266. package/dist/commands/claude/plugin/plugin-changelog.js.map +1 -1
  267. package/dist/commands/claude/plugin/plugin-files.d.ts +21 -2
  268. package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -1
  269. package/dist/commands/claude/plugin/plugin-files.js +65 -32
  270. package/dist/commands/claude/plugin/plugin-files.js.map +1 -1
  271. package/dist/commands/claude/plugin/plugin-validators.d.ts +13 -0
  272. package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -1
  273. package/dist/commands/claude/plugin/plugin-validators.js +64 -16
  274. package/dist/commands/claude/plugin/plugin-validators.js.map +1 -1
  275. package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
  276. package/dist/commands/claude/plugin/tree-copy.js +63 -37
  277. package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
  278. package/dist/commands/claude/plugin/uninstall-schema.d.ts +112 -0
  279. package/dist/commands/claude/plugin/uninstall-schema.d.ts.map +1 -0
  280. package/dist/commands/claude/plugin/uninstall-schema.js +28 -0
  281. package/dist/commands/claude/plugin/uninstall-schema.js.map +1 -0
  282. package/dist/commands/claude/plugin/uninstall.d.ts +57 -0
  283. package/dist/commands/claude/plugin/uninstall.d.ts.map +1 -1
  284. package/dist/commands/claude/plugin/uninstall.js +176 -64
  285. package/dist/commands/claude/plugin/uninstall.js.map +1 -1
  286. package/dist/commands/consistency-check.d.ts.map +1 -1
  287. package/dist/commands/consistency-check.js +8 -6
  288. package/dist/commands/consistency-check.js.map +1 -1
  289. package/dist/commands/corpus/index.d.ts.map +1 -1
  290. package/dist/commands/corpus/index.js +26 -10
  291. package/dist/commands/corpus/index.js.map +1 -1
  292. package/dist/commands/corpus/report.d.ts +34 -16
  293. package/dist/commands/corpus/report.d.ts.map +1 -1
  294. package/dist/commands/corpus/report.js +36 -18
  295. package/dist/commands/corpus/report.js.map +1 -1
  296. package/dist/commands/corpus/runner.d.ts +25 -20
  297. package/dist/commands/corpus/runner.d.ts.map +1 -1
  298. package/dist/commands/corpus/runner.js +123 -67
  299. package/dist/commands/corpus/runner.js.map +1 -1
  300. package/dist/commands/corpus/scan-schema.d.ts +127 -0
  301. package/dist/commands/corpus/scan-schema.d.ts.map +1 -0
  302. package/dist/commands/corpus/scan-schema.js +31 -0
  303. package/dist/commands/corpus/scan-schema.js.map +1 -0
  304. package/dist/commands/corpus/scan.d.ts +31 -0
  305. package/dist/commands/corpus/scan.d.ts.map +1 -1
  306. package/dist/commands/corpus/scan.js +124 -50
  307. package/dist/commands/corpus/scan.js.map +1 -1
  308. package/dist/commands/corpus/seed.d.ts +11 -8
  309. package/dist/commands/corpus/seed.d.ts.map +1 -1
  310. package/dist/commands/corpus/seed.js +29 -11
  311. package/dist/commands/corpus/seed.js.map +1 -1
  312. package/dist/commands/doctor-render.d.ts +52 -0
  313. package/dist/commands/doctor-render.d.ts.map +1 -0
  314. package/dist/commands/doctor-render.js +110 -0
  315. package/dist/commands/doctor-render.js.map +1 -0
  316. package/dist/commands/doctor-schema.d.ts +191 -0
  317. package/dist/commands/doctor-schema.d.ts.map +1 -0
  318. package/dist/commands/doctor-schema.js +44 -0
  319. package/dist/commands/doctor-schema.js.map +1 -0
  320. package/dist/commands/doctor.d.ts +7 -62
  321. package/dist/commands/doctor.d.ts.map +1 -1
  322. package/dist/commands/doctor.js +126 -165
  323. package/dist/commands/doctor.js.map +1 -1
  324. package/dist/commands/inventory-schema.d.ts +7297 -0
  325. package/dist/commands/inventory-schema.d.ts.map +1 -0
  326. package/dist/commands/inventory-schema.js +28 -0
  327. package/dist/commands/inventory-schema.js.map +1 -0
  328. package/dist/commands/inventory.d.ts +1 -1
  329. package/dist/commands/inventory.d.ts.map +1 -1
  330. package/dist/commands/inventory.js +89 -41
  331. package/dist/commands/inventory.js.map +1 -1
  332. package/dist/commands/mcp/index.d.ts.map +1 -1
  333. package/dist/commands/mcp/index.js +15 -0
  334. package/dist/commands/mcp/index.js.map +1 -1
  335. package/dist/commands/mcp/list-collections-schema.d.ts +101 -0
  336. package/dist/commands/mcp/list-collections-schema.d.ts.map +1 -0
  337. package/dist/commands/mcp/list-collections-schema.js +22 -0
  338. package/dist/commands/mcp/list-collections-schema.js.map +1 -0
  339. package/dist/commands/mcp/list-collections.d.ts +1 -1
  340. package/dist/commands/mcp/list-collections.d.ts.map +1 -1
  341. package/dist/commands/mcp/list-collections.js +19 -17
  342. package/dist/commands/mcp/list-collections.js.map +1 -1
  343. package/dist/commands/mcp/serve.d.ts +5 -0
  344. package/dist/commands/mcp/serve.d.ts.map +1 -1
  345. package/dist/commands/mcp/serve.js +29 -15
  346. package/dist/commands/mcp/serve.js.map +1 -1
  347. package/dist/commands/okf/index.d.ts.map +1 -1
  348. package/dist/commands/okf/index.js +13 -10
  349. package/dist/commands/okf/index.js.map +1 -1
  350. package/dist/commands/okf/validate-schema.d.ts +171 -0
  351. package/dist/commands/okf/validate-schema.d.ts.map +1 -0
  352. package/dist/commands/okf/validate-schema.js +44 -0
  353. package/dist/commands/okf/validate-schema.js.map +1 -0
  354. package/dist/commands/okf/validate.d.ts +16 -145
  355. package/dist/commands/okf/validate.d.ts.map +1 -1
  356. package/dist/commands/okf/validate.js +63 -52
  357. package/dist/commands/okf/validate.js.map +1 -1
  358. package/dist/commands/orchestrator-schema.d.ts +419 -0
  359. package/dist/commands/orchestrator-schema.d.ts.map +1 -0
  360. package/dist/commands/orchestrator-schema.js +91 -0
  361. package/dist/commands/orchestrator-schema.js.map +1 -0
  362. package/dist/commands/phase-utils.d.ts +188 -220
  363. package/dist/commands/phase-utils.d.ts.map +1 -1
  364. package/dist/commands/phase-utils.js +210 -258
  365. package/dist/commands/phase-utils.js.map +1 -1
  366. package/dist/commands/positional-args.d.ts +13 -11
  367. package/dist/commands/positional-args.d.ts.map +1 -1
  368. package/dist/commands/positional-args.js +16 -15
  369. package/dist/commands/positional-args.js.map +1 -1
  370. package/dist/commands/rag/admin-schema.d.ts +152 -0
  371. package/dist/commands/rag/admin-schema.d.ts.map +1 -0
  372. package/dist/commands/rag/admin-schema.js +31 -0
  373. package/dist/commands/rag/admin-schema.js.map +1 -0
  374. package/dist/commands/rag/clear-command.d.ts.map +1 -1
  375. package/dist/commands/rag/clear-command.js +30 -15
  376. package/dist/commands/rag/clear-command.js.map +1 -1
  377. package/dist/commands/rag/command-helpers.d.ts +31 -7
  378. package/dist/commands/rag/command-helpers.d.ts.map +1 -1
  379. package/dist/commands/rag/command-helpers.js +41 -21
  380. package/dist/commands/rag/command-helpers.js.map +1 -1
  381. package/dist/commands/rag/index-command.d.ts +37 -48
  382. package/dist/commands/rag/index-command.d.ts.map +1 -1
  383. package/dist/commands/rag/index-command.js +80 -65
  384. package/dist/commands/rag/index-command.js.map +1 -1
  385. package/dist/commands/rag/index-schema.d.ts +107 -0
  386. package/dist/commands/rag/index-schema.d.ts.map +1 -0
  387. package/dist/commands/rag/index-schema.js +34 -0
  388. package/dist/commands/rag/index-schema.js.map +1 -0
  389. package/dist/commands/rag/index.d.ts.map +1 -1
  390. package/dist/commands/rag/index.js +88 -41
  391. package/dist/commands/rag/index.js.map +1 -1
  392. package/dist/commands/rag/query-command.d.ts +18 -4
  393. package/dist/commands/rag/query-command.d.ts.map +1 -1
  394. package/dist/commands/rag/query-command.js +42 -27
  395. package/dist/commands/rag/query-command.js.map +1 -1
  396. package/dist/commands/rag/query-schema.d.ts +363 -0
  397. package/dist/commands/rag/query-schema.d.ts.map +1 -0
  398. package/dist/commands/rag/query-schema.js +59 -0
  399. package/dist/commands/rag/query-schema.js.map +1 -0
  400. package/dist/commands/rag/stats-command.d.ts.map +1 -1
  401. package/dist/commands/rag/stats-command.js +19 -18
  402. package/dist/commands/rag/stats-command.js.map +1 -1
  403. package/dist/commands/resources/check-progress.d.ts +79 -13
  404. package/dist/commands/resources/check-progress.d.ts.map +1 -1
  405. package/dist/commands/resources/check-progress.js +112 -11
  406. package/dist/commands/resources/check-progress.js.map +1 -1
  407. package/dist/commands/resources/check-schema.d.ts +335 -0
  408. package/dist/commands/resources/check-schema.d.ts.map +1 -0
  409. package/dist/commands/resources/check-schema.js +104 -0
  410. package/dist/commands/resources/check-schema.js.map +1 -0
  411. package/dist/commands/resources/check-supervisor.d.ts +329 -71
  412. package/dist/commands/resources/check-supervisor.d.ts.map +1 -1
  413. package/dist/commands/resources/check-supervisor.js +507 -107
  414. package/dist/commands/resources/check-supervisor.js.map +1 -1
  415. package/dist/commands/resources/check.d.ts +88 -254
  416. package/dist/commands/resources/check.d.ts.map +1 -1
  417. package/dist/commands/resources/check.js +537 -310
  418. package/dist/commands/resources/check.js.map +1 -1
  419. package/dist/commands/resources/index.d.ts.map +1 -1
  420. package/dist/commands/resources/index.js +189 -103
  421. package/dist/commands/resources/index.js.map +1 -1
  422. package/dist/commands/resources/query-schema.d.ts +188 -0
  423. package/dist/commands/resources/query-schema.d.ts.map +1 -0
  424. package/dist/commands/resources/query-schema.js +48 -0
  425. package/dist/commands/resources/query-schema.js.map +1 -0
  426. package/dist/commands/resources/query.d.ts +18 -13
  427. package/dist/commands/resources/query.d.ts.map +1 -1
  428. package/dist/commands/resources/query.js +61 -49
  429. package/dist/commands/resources/query.js.map +1 -1
  430. package/dist/commands/resources/scan-schema.d.ts +195 -0
  431. package/dist/commands/resources/scan-schema.d.ts.map +1 -0
  432. package/dist/commands/resources/scan-schema.js +53 -0
  433. package/dist/commands/resources/scan-schema.js.map +1 -0
  434. package/dist/commands/resources/scan.d.ts +26 -3
  435. package/dist/commands/resources/scan.d.ts.map +1 -1
  436. package/dist/commands/resources/scan.js +51 -53
  437. package/dist/commands/resources/scan.js.map +1 -1
  438. package/dist/commands/resources/validate-schema.d.ts +326 -0
  439. package/dist/commands/resources/validate-schema.d.ts.map +1 -0
  440. package/dist/commands/resources/validate-schema.js +60 -0
  441. package/dist/commands/resources/validate-schema.js.map +1 -0
  442. package/dist/commands/resources/validate.d.ts +45 -169
  443. package/dist/commands/resources/validate.d.ts.map +1 -1
  444. package/dist/commands/resources/validate.js +221 -485
  445. package/dist/commands/resources/validate.js.map +1 -1
  446. package/dist/commands/skill/review-checklist.d.ts.map +1 -1
  447. package/dist/commands/skill/review-checklist.js +0 -1
  448. package/dist/commands/skill/review-checklist.js.map +1 -1
  449. package/dist/commands/skill/review-schema.d.ts +278 -0
  450. package/dist/commands/skill/review-schema.d.ts.map +1 -0
  451. package/dist/commands/skill/review-schema.js +46 -0
  452. package/dist/commands/skill/review-schema.js.map +1 -0
  453. package/dist/commands/skill/review.d.ts +8 -234
  454. package/dist/commands/skill/review.d.ts.map +1 -1
  455. package/dist/commands/skill/review.js +54 -77
  456. package/dist/commands/skill/review.js.map +1 -1
  457. package/dist/commands/skill/test/auth-flags.d.ts +3 -0
  458. package/dist/commands/skill/test/auth-flags.d.ts.map +1 -1
  459. package/dist/commands/skill/test/auth-flags.js +6 -2
  460. package/dist/commands/skill/test/auth-flags.js.map +1 -1
  461. package/dist/commands/skill/test/configure-schema.d.ts +67 -0
  462. package/dist/commands/skill/test/configure-schema.d.ts.map +1 -0
  463. package/dist/commands/skill/test/configure-schema.js +27 -0
  464. package/dist/commands/skill/test/configure-schema.js.map +1 -0
  465. package/dist/commands/skill/test/configure.d.ts +12 -5
  466. package/dist/commands/skill/test/configure.d.ts.map +1 -1
  467. package/dist/commands/skill/test/configure.js +101 -31
  468. package/dist/commands/skill/test/configure.js.map +1 -1
  469. package/dist/commands/skill/test/run-schema.d.ts +107 -0
  470. package/dist/commands/skill/test/run-schema.d.ts.map +1 -0
  471. package/dist/commands/skill/test/run-schema.js +36 -0
  472. package/dist/commands/skill/test/run-schema.js.map +1 -0
  473. package/dist/commands/skill/test/run.d.ts +3 -2
  474. package/dist/commands/skill/test/run.d.ts.map +1 -1
  475. package/dist/commands/skill/test/run.js +316 -155
  476. package/dist/commands/skill/test/run.js.map +1 -1
  477. package/dist/commands/skills/build-schema.d.ts +199 -0
  478. package/dist/commands/skills/build-schema.d.ts.map +1 -0
  479. package/dist/commands/skills/build-schema.js +55 -0
  480. package/dist/commands/skills/build-schema.js.map +1 -0
  481. package/dist/commands/skills/build.d.ts +95 -298
  482. package/dist/commands/skills/build.d.ts.map +1 -1
  483. package/dist/commands/skills/build.js +415 -818
  484. package/dist/commands/skills/build.js.map +1 -1
  485. package/dist/commands/skills/command-helpers.d.ts +5 -11
  486. package/dist/commands/skills/command-helpers.d.ts.map +1 -1
  487. package/dist/commands/skills/command-helpers.js +7 -17
  488. package/dist/commands/skills/command-helpers.js.map +1 -1
  489. package/dist/commands/skills/index.js +12 -6
  490. package/dist/commands/skills/index.js.map +1 -1
  491. package/dist/commands/skills/install-schema.d.ts +153 -0
  492. package/dist/commands/skills/install-schema.d.ts.map +1 -0
  493. package/dist/commands/skills/install-schema.js +44 -0
  494. package/dist/commands/skills/install-schema.js.map +1 -0
  495. package/dist/commands/skills/install.d.ts +76 -8
  496. package/dist/commands/skills/install.d.ts.map +1 -1
  497. package/dist/commands/skills/install.js +230 -194
  498. package/dist/commands/skills/install.js.map +1 -1
  499. package/dist/commands/skills/list-schema.d.ts +145 -0
  500. package/dist/commands/skills/list-schema.d.ts.map +1 -0
  501. package/dist/commands/skills/list-schema.js +37 -0
  502. package/dist/commands/skills/list-schema.js.map +1 -0
  503. package/dist/commands/skills/list.d.ts +39 -8
  504. package/dist/commands/skills/list.d.ts.map +1 -1
  505. package/dist/commands/skills/list.js +110 -122
  506. package/dist/commands/skills/list.js.map +1 -1
  507. package/dist/commands/skills/package-schema.d.ts +98 -0
  508. package/dist/commands/skills/package-schema.d.ts.map +1 -0
  509. package/dist/commands/skills/package-schema.js +32 -0
  510. package/dist/commands/skills/package-schema.js.map +1 -0
  511. package/dist/commands/skills/package.d.ts +85 -14
  512. package/dist/commands/skills/package.d.ts.map +1 -1
  513. package/dist/commands/skills/package.js +288 -207
  514. package/dist/commands/skills/package.js.map +1 -1
  515. package/dist/commands/skills/scope-guard.d.ts +27 -20
  516. package/dist/commands/skills/scope-guard.d.ts.map +1 -1
  517. package/dist/commands/skills/scope-guard.js +43 -28
  518. package/dist/commands/skills/scope-guard.js.map +1 -1
  519. package/dist/commands/skills/skill-discovery.d.ts +1 -1
  520. package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
  521. package/dist/commands/skills/skill-discovery.js +40 -19
  522. package/dist/commands/skills/skill-discovery.js.map +1 -1
  523. package/dist/commands/skills/source-resolvers.d.ts +58 -8
  524. package/dist/commands/skills/source-resolvers.d.ts.map +1 -1
  525. package/dist/commands/skills/source-resolvers.js +113 -38
  526. package/dist/commands/skills/source-resolvers.js.map +1 -1
  527. package/dist/commands/skills/validate-command.d.ts.map +1 -1
  528. package/dist/commands/skills/validate-command.js +31 -51
  529. package/dist/commands/skills/validate-command.js.map +1 -1
  530. package/dist/commands/skills/validate-schema.d.ts +199 -0
  531. package/dist/commands/skills/validate-schema.d.ts.map +1 -0
  532. package/dist/commands/skills/validate-schema.js +44 -0
  533. package/dist/commands/skills/validate-schema.js.map +1 -0
  534. package/dist/commands/skills/validate.d.ts +100 -136
  535. package/dist/commands/skills/validate.d.ts.map +1 -1
  536. package/dist/commands/skills/validate.js +257 -343
  537. package/dist/commands/skills/validate.js.map +1 -1
  538. package/dist/commands/validate.d.ts +17 -5
  539. package/dist/commands/validate.d.ts.map +1 -1
  540. package/dist/commands/validate.js +139 -94
  541. package/dist/commands/validate.js.map +1 -1
  542. package/dist/commands/verify.d.ts +121 -110
  543. package/dist/commands/verify.d.ts.map +1 -1
  544. package/dist/commands/verify.js +230 -294
  545. package/dist/commands/verify.js.map +1 -1
  546. package/dist/index.d.ts +1 -1
  547. package/dist/index.d.ts.map +1 -1
  548. package/dist/index.js +1 -1
  549. package/dist/index.js.map +1 -1
  550. package/dist/report-schemas.d.ts +12398 -35
  551. package/dist/report-schemas.d.ts.map +1 -1
  552. package/dist/report-schemas.js +624 -66
  553. package/dist/report-schemas.js.map +1 -1
  554. package/dist/skill-resolution/packaging-config.js +2 -2
  555. package/dist/skill-resolution/packaging-config.js.map +1 -1
  556. package/dist/skill-resolution/resolve-skill-reference.d.ts.map +1 -1
  557. package/dist/skill-resolution/resolve-skill-reference.js +20 -13
  558. package/dist/skill-resolution/resolve-skill-reference.js.map +1 -1
  559. package/dist/utils/agent-discovery.d.ts +34 -1
  560. package/dist/utils/agent-discovery.d.ts.map +1 -1
  561. package/dist/utils/agent-discovery.js +80 -38
  562. package/dist/utils/agent-discovery.js.map +1 -1
  563. package/dist/utils/claude-context-lens.d.ts +13 -6
  564. package/dist/utils/claude-context-lens.d.ts.map +1 -1
  565. package/dist/utils/claude-context-lens.js +11 -12
  566. package/dist/utils/claude-context-lens.js.map +1 -1
  567. package/dist/utils/command-error-codes.d.ts +12 -0
  568. package/dist/utils/command-error-codes.d.ts.map +1 -0
  569. package/dist/utils/command-error-codes.js +12 -0
  570. package/dist/utils/command-error-codes.js.map +1 -0
  571. package/dist/utils/command-refusal.d.ts +58 -0
  572. package/dist/utils/command-refusal.d.ts.map +1 -0
  573. package/dist/utils/command-refusal.js +170 -0
  574. package/dist/utils/command-refusal.js.map +1 -0
  575. package/dist/utils/commander-ending.d.ts +40 -0
  576. package/dist/utils/commander-ending.d.ts.map +1 -0
  577. package/dist/utils/commander-ending.js +42 -0
  578. package/dist/utils/commander-ending.js.map +1 -0
  579. package/dist/utils/config-loader.d.ts +13 -8
  580. package/dist/utils/config-loader.d.ts.map +1 -1
  581. package/dist/utils/config-loader.js +84 -45
  582. package/dist/utils/config-loader.js.map +1 -1
  583. package/dist/utils/corpus-target.d.ts +1 -1
  584. package/dist/utils/corpus-target.d.ts.map +1 -1
  585. package/dist/utils/corpus-target.js +44 -5
  586. package/dist/utils/corpus-target.js.map +1 -1
  587. package/dist/utils/debug-diagnostics.d.ts +18 -0
  588. package/dist/utils/debug-diagnostics.d.ts.map +1 -0
  589. package/dist/utils/debug-diagnostics.js +23 -0
  590. package/dist/utils/debug-diagnostics.js.map +1 -0
  591. package/dist/utils/document-writer.d.ts +191 -0
  592. package/dist/utils/document-writer.d.ts.map +1 -0
  593. package/dist/utils/document-writer.js +319 -0
  594. package/dist/utils/document-writer.js.map +1 -0
  595. package/dist/utils/help-loader.d.ts +2 -2
  596. package/dist/utils/help-loader.js +2 -2
  597. package/dist/utils/install-plan.d.ts +99 -0
  598. package/dist/utils/install-plan.d.ts.map +1 -0
  599. package/dist/utils/install-plan.js +146 -0
  600. package/dist/utils/install-plan.js.map +1 -0
  601. package/dist/utils/issue-anchor.d.ts +1 -1
  602. package/dist/utils/issue-anchor.d.ts.map +1 -1
  603. package/dist/utils/issue-anchor.js.map +1 -1
  604. package/dist/utils/issue-rendering.d.ts +8 -3
  605. package/dist/utils/issue-rendering.d.ts.map +1 -1
  606. package/dist/utils/issue-rendering.js +4 -0
  607. package/dist/utils/issue-rendering.js.map +1 -1
  608. package/dist/utils/lens-population.d.ts +20 -0
  609. package/dist/utils/lens-population.d.ts.map +1 -0
  610. package/dist/utils/lens-population.js +15 -0
  611. package/dist/utils/lens-population.js.map +1 -0
  612. package/dist/utils/marketplace-io.d.ts +63 -0
  613. package/dist/utils/marketplace-io.d.ts.map +1 -0
  614. package/dist/utils/marketplace-io.js +63 -0
  615. package/dist/utils/marketplace-io.js.map +1 -0
  616. package/dist/utils/operator-notices.d.ts +97 -0
  617. package/dist/utils/operator-notices.d.ts.map +1 -0
  618. package/dist/utils/operator-notices.js +115 -0
  619. package/dist/utils/operator-notices.js.map +1 -0
  620. package/dist/utils/optional-backend.d.ts +18 -15
  621. package/dist/utils/optional-backend.d.ts.map +1 -1
  622. package/dist/utils/optional-backend.js +22 -33
  623. package/dist/utils/optional-backend.js.map +1 -1
  624. package/dist/utils/output.d.ts +5 -43
  625. package/dist/utils/output.d.ts.map +1 -1
  626. package/dist/utils/output.js +8 -63
  627. package/dist/utils/output.js.map +1 -1
  628. package/dist/utils/package-json.d.ts +3 -4
  629. package/dist/utils/package-json.d.ts.map +1 -1
  630. package/dist/utils/package-json.js +8 -8
  631. package/dist/utils/package-json.js.map +1 -1
  632. package/dist/utils/population-wiring.d.ts +31 -38
  633. package/dist/utils/population-wiring.d.ts.map +1 -1
  634. package/dist/utils/population-wiring.js +38 -32
  635. package/dist/utils/population-wiring.js.map +1 -1
  636. package/dist/utils/project-root-policy.d.ts +74 -1
  637. package/dist/utils/project-root-policy.d.ts.map +1 -1
  638. package/dist/utils/project-root-policy.js +146 -8
  639. package/dist/utils/project-root-policy.js.map +1 -1
  640. package/dist/utils/projection-lenses.d.ts +25 -7
  641. package/dist/utils/projection-lenses.d.ts.map +1 -1
  642. package/dist/utils/projection-lenses.js +20 -6
  643. package/dist/utils/projection-lenses.js.map +1 -1
  644. package/dist/utils/projection-query.d.ts +18 -11
  645. package/dist/utils/projection-query.d.ts.map +1 -1
  646. package/dist/utils/projection-query.js +47 -28
  647. package/dist/utils/projection-query.js.map +1 -1
  648. package/dist/utils/projection-store.d.ts +2 -2
  649. package/dist/utils/projection-store.d.ts.map +1 -1
  650. package/dist/utils/projection-store.js +74 -45
  651. package/dist/utils/projection-store.js.map +1 -1
  652. package/dist/utils/rag-database.d.ts +61 -0
  653. package/dist/utils/rag-database.d.ts.map +1 -0
  654. package/dist/utils/rag-database.js +178 -0
  655. package/dist/utils/rag-database.js.map +1 -0
  656. package/dist/utils/relation-limits.d.ts +7 -2
  657. package/dist/utils/relation-limits.d.ts.map +1 -1
  658. package/dist/utils/relation-limits.js +6 -1
  659. package/dist/utils/relation-limits.js.map +1 -1
  660. package/dist/utils/relativize-paths.d.ts +23 -0
  661. package/dist/utils/relativize-paths.d.ts.map +1 -1
  662. package/dist/utils/relativize-paths.js +32 -1
  663. package/dist/utils/relativize-paths.js.map +1 -1
  664. package/dist/utils/resource-loader.d.ts +78 -32
  665. package/dist/utils/resource-loader.d.ts.map +1 -1
  666. package/dist/utils/resource-loader.js +134 -66
  667. package/dist/utils/resource-loader.js.map +1 -1
  668. package/dist/utils/run-integrity.d.ts +64 -31
  669. package/dist/utils/run-integrity.d.ts.map +1 -1
  670. package/dist/utils/run-integrity.js +76 -35
  671. package/dist/utils/run-integrity.js.map +1 -1
  672. package/dist/utils/scope-locations.d.ts +7 -5
  673. package/dist/utils/scope-locations.d.ts.map +1 -1
  674. package/dist/utils/scope-locations.js +37 -12
  675. package/dist/utils/scope-locations.js.map +1 -1
  676. package/dist/utils/staging-dir.d.ts +7 -0
  677. package/dist/utils/staging-dir.d.ts.map +1 -0
  678. package/dist/utils/staging-dir.js +12 -0
  679. package/dist/utils/staging-dir.js.map +1 -0
  680. package/dist/utils/url-redact.d.ts +9 -0
  681. package/dist/utils/url-redact.d.ts.map +1 -1
  682. package/dist/utils/url-redact.js +13 -0
  683. package/dist/utils/url-redact.js.map +1 -1
  684. package/dist/utils/user-context-scanner.d.ts +3 -2
  685. package/dist/utils/user-context-scanner.d.ts.map +1 -1
  686. package/dist/utils/user-context-scanner.js +24 -4
  687. package/dist/utils/user-context-scanner.js.map +1 -1
  688. package/dist/utils/validate-help-files.d.ts.map +1 -1
  689. package/dist/utils/validate-help-files.js +8 -14
  690. package/dist/utils/validate-help-files.js.map +1 -1
  691. package/dist/utils/vat-bin-path.d.ts.map +1 -1
  692. package/dist/utils/vat-bin-path.js +3 -3
  693. package/dist/utils/vat-bin-path.js.map +1 -1
  694. package/dist/utils/verdict-helpers.d.ts.map +1 -1
  695. package/dist/utils/verdict-helpers.js +5 -5
  696. package/dist/utils/verdict-helpers.js.map +1 -1
  697. package/docs/agent.md +347 -2
  698. package/docs/audit.md +312 -89
  699. package/docs/doctor.md +65 -19
  700. package/docs/index.md +571 -20
  701. package/docs/mcp.md +64 -12
  702. package/docs/rag.md +176 -48
  703. package/docs/resources.md +257 -71
  704. package/docs/skill-test.md +148 -19
  705. package/docs/skills.md +459 -174
  706. package/package.json +17 -20
  707. package/schemas/agent-build.json +268 -0
  708. package/schemas/agent-import.json +252 -0
  709. package/schemas/agent-install.json +260 -0
  710. package/schemas/agent-installed.json +287 -0
  711. package/schemas/agent-list.json +279 -0
  712. package/schemas/agent-uninstall.json +260 -0
  713. package/schemas/agent-validate.json +279 -0
  714. package/schemas/ard-emit.json +228 -107
  715. package/schemas/audit-settings.json +472 -0
  716. package/schemas/audit.json +635 -0
  717. package/schemas/cache-clear.json +273 -0
  718. package/schemas/claude-marketplace-publish.json +286 -0
  719. package/schemas/claude-marketplace-validate.json +352 -0
  720. package/schemas/claude-org-not-implemented.json +239 -0
  721. package/schemas/claude-plugin-build.json +446 -0
  722. package/schemas/claude-plugin-install.json +291 -0
  723. package/schemas/claude-plugin-list.json +326 -0
  724. package/schemas/claude-plugin-uninstall.json +272 -0
  725. package/schemas/corpus-audit.json +635 -0
  726. package/schemas/corpus-scan.json +293 -0
  727. package/schemas/doctor.json +299 -0
  728. package/schemas/inventory.json +982 -0
  729. package/schemas/mcp-list-collections.json +268 -0
  730. package/schemas/okf-validate.json +224 -106
  731. package/schemas/orchestrator.json +299 -0
  732. package/schemas/rag-clear.json +253 -0
  733. package/schemas/rag-index.json +273 -0
  734. package/schemas/rag-query.json +365 -0
  735. package/schemas/rag-stats.json +269 -0
  736. package/schemas/resources-check.json +280 -118
  737. package/schemas/resources-query.json +333 -0
  738. package/schemas/resources-scan.json +321 -0
  739. package/schemas/resources-validate.json +332 -0
  740. package/schemas/skill-review.json +224 -106
  741. package/schemas/skill-test-configure.json +256 -0
  742. package/schemas/skill-test-run.json +296 -0
  743. package/schemas/skills-build.json +325 -0
  744. package/schemas/skills-install.json +287 -0
  745. package/schemas/skills-list.json +283 -0
  746. package/schemas/skills-package.json +270 -0
  747. package/schemas/skills-validate.json +285 -0
  748. package/dist/commands/skills/shared.d.ts +0 -29
  749. package/dist/commands/skills/shared.d.ts.map +0 -1
  750. package/dist/commands/skills/shared.js +0 -33
  751. package/dist/commands/skills/shared.js.map +0 -1
  752. package/dist/utils/command-error.d.ts +0 -189
  753. package/dist/utils/command-error.d.ts.map +0 -1
  754. package/dist/utils/command-error.js +0 -230
  755. package/dist/utils/command-error.js.map +0 -1
@@ -1,14 +1,18 @@
1
1
  /**
2
2
  * `vat claude org skills` — manage organization skills via Skills API.
3
3
  */
4
- import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync } from 'node:fs';
4
+ import { readFileSync, readdirSync } from 'node:fs';
5
5
  import { basename } from 'node:path';
6
- import { API_SKILL_MAX_UPLOAD_BYTES, collectNonPortableAssetReferenceIssues, collectNonPortableCommandIssues, collectUnqualifiedMcpToolIssues, declaredSkillNameIn, describeOversizeBundle, evalSuiteUnitPath, formatBytes, NEVER_UPLOADED_DIR_NAMES, readDeclaredSkillName, } from '@vibe-agent-toolkit/agent-skills';
6
+ import { API_SKILL_MAX_UPLOAD_BYTES, collectNonPortableAssetReferenceIssues, collectNonPortableCommandIssues, collectUnqualifiedMcpToolIssues, declaredSkillNameIn, describeOversizeBundle, evalSuiteUnitPath, formatBytes, hostAddedToSkillZip, NEVER_UPLOADED_DIR_NAMES, readDeclaredSkillName, } from '@vibe-agent-toolkit/agent-skills';
7
7
  import { ApiRequestError, ApiTransportError, buildMultipartFormData, skillVersionsPath, } from '@vibe-agent-toolkit/claude-marketplace';
8
8
  import { createAllowUsageLedger, runValidationFramework } from '@vibe-agent-toolkit/schema';
9
- import { direntKindFollowingSync, isAbsoluteAnyPlatform, isFilesystemAccessError, normalizedTmpdir, safePath, toForwardSlashAnyPlatform, } from '@vibe-agent-toolkit/utils';
9
+ import { ARCHIVE_REFUSED_CODE, archiveEntryPlace, direntKindFollowingSync, everywhere, forEachInOrder, isAbsoluteAnyPlatform, isArchiveEntryReadRefusal, isVatError, pathPresent, requireFollowedStatSync, safePath, toForwardSlash, toForwardSlashAnyPlatform, withTempDir } from '@vibe-agent-toolkit/utils';
10
10
  import { Command } from 'commander';
11
11
  import { resolveSkillPackagingConfig } from '../../../skill-resolution/packaging-config.js';
12
+ import { CommandRefusalError, errorMessageOf, refusalCodeOf } from '../../../utils/command-refusal.js';
13
+ import { leftoverIssueOf } from '../../../utils/document-writer.js';
14
+ import { requireSkillZipLayout } from '../../../utils/install-plan.js';
15
+ import { requireInputPath } from '../../../utils/project-root-policy.js';
12
16
  import { downloadNpmPackage } from '../plugin/helpers.js';
13
17
  import { autopaginateSkills, executeOrgCommand, orgCommandFailure } from './helpers.js';
14
18
  const SKILL_ID_ARG = '<skill-id>';
@@ -47,7 +51,7 @@ function readSkillUploadResponse(endpoint, raw, fields) {
47
51
  [fields.version, version], [fields.createdAt, createdAt],
48
52
  ].filter(([, value]) => value === undefined).map(([key]) => String(key));
49
53
  const present = Object.keys(body).join(', ') || '(none)';
50
- throw new Error(`${endpoint} returned a body with no usable ${missing.join(', ')}. Keys present: ${present}. `
54
+ throw new CommandRefusalError('EXTERNAL_API_FAILED', `${endpoint} returned a body with no usable ${missing.join(', ')}. Keys present: ${present}. `
51
55
  + 'Refusing to report success for an upload whose identifiers cannot be read.');
52
56
  }
53
57
  return { id, displayTitle, version, createdAt };
@@ -86,7 +90,7 @@ export function readCreateSkillResponse(raw) {
86
90
  * `skill_deleted` came back from a live `DELETE /v1/skills/{id}`;
87
91
  * `skill_version_deleted` is the plausible spelling for the version endpoint and
88
92
  * has never been seen. A single guessed string would make every version delete
89
- * report `deleted: false` — and now exit 1 — if the vendor spells it differently
93
+ * report `deleted: false` — and now exit 2 — if the vendor spells it differently
90
94
  * by one character. Accepting either keeps the check honest about what it knows:
91
95
  * a body naming something that is neither is a real divergence worth failing on.
92
96
  */
@@ -106,6 +110,8 @@ export const SKILL_DELETED_TYPES = ['skill_deleted'];
106
110
  * {@link readDeleteResponse} for why this is two and not one.
107
111
  */
108
112
  export const SKILL_VERSION_DELETED_TYPES = ['skill_version_deleted', 'skill_deleted'];
113
+ /** A delete the API answered with an outcome other than a deletion: nothing was destroyed. */
114
+ const NOT_CONFIRMED = { kind: 'failed', cause: 'the API named an outcome other than a deletion' };
109
115
  /**
110
116
  * A delete's document, tagged as a FAILED run when the API said the thing was
111
117
  * not deleted.
@@ -123,7 +129,7 @@ export const SKILL_VERSION_DELETED_TYPES = ['skill_version_deleted', 'skill_dele
123
129
  */
124
130
  export function reportDelete(raw, requestedId, expectedTypes) {
125
131
  const result = readDeleteResponse(raw, requestedId, expectedTypes);
126
- return result.deleted ? result : orgCommandFailure(result);
132
+ return result.deleted ? result : orgCommandFailure(result, NOT_CONFIRMED);
127
133
  }
128
134
  /**
129
135
  * A version delete's document — the same verdict as {@link reportDelete}, about
@@ -148,7 +154,7 @@ export function reportDelete(raw, requestedId, expectedTypes) {
148
154
  export function reportVersionDelete(raw, skillId, version) {
149
155
  const { deleted } = readDeleteResponse(raw, skillId, SKILL_VERSION_DELETED_TYPES);
150
156
  const document = { id: skillId, version, deleted };
151
- return deleted ? document : orgCommandFailure(document);
157
+ return deleted ? document : orgCommandFailure(document, NOT_CONFIRMED);
152
158
  }
153
159
  /**
154
160
  * Add the versions a `--all` run destroyed to its report, preserving whatever
@@ -160,9 +166,9 @@ export function reportVersionDelete(raw, skillId, version) {
160
166
  * skill's fields and publish the tag as part of the operator's document.
161
167
  */
162
168
  export function mergeDeleteReport(result, deletedVersions) {
163
- const failed = 'orgCommandFailed' in result;
164
- const document = { ...(failed ? result.document : result), deletedVersions };
165
- return failed ? orgCommandFailure(document) : document;
169
+ if (!('orgCommandFailed' in result))
170
+ return { ...result, deletedVersions };
171
+ return orgCommandFailure({ ...result.document, deletedVersions }, result.outcome);
166
172
  }
167
173
  /** Read `POST /v1/skills/{id}/versions`. */
168
174
  export function readSkillVersionResponse(raw) {
@@ -230,7 +236,7 @@ export function buildUploadBodyOrRefuse(fields, files, bundleRoot) {
230
236
  if (multipart.body.length > API_SKILL_MAX_UPLOAD_BYTES) {
231
237
  const sized = files.map(f => ({ path: bundleRelativeName(f.filename, bundleRoot), bytes: f.content.length }));
232
238
  const measure = { of: 'upload-request', bytes: multipart.body.length };
233
- throw new Error(`${describeOversizeBundle(sized, measure)}. The API will refuse this upload.`);
239
+ throw new CommandRefusalError('USAGE_INVALID', `${describeOversizeBundle(sized, measure)}. The API will refuse this upload.`);
234
240
  }
235
241
  return multipart;
236
242
  }
@@ -413,10 +419,10 @@ export function explainAnsweredNothing(error, bodyBytes) {
413
419
  if (!(error instanceof ApiTransportError))
414
420
  return error;
415
421
  if (error.bytesSent === 0) {
416
- return new Error(`${error.message}\nNo byte of the request left this machine, so nothing was created and `
422
+ return new CommandRefusalError('EXTERNAL_API_FAILED', `${error.message}\nNo byte of the request left this machine, so nothing was created and `
417
423
  + 'there is nothing to clean up. Fix the connection and re-run the same command.', { cause: error });
418
424
  }
419
- return new Error(`${error.message}\nThe connection closed before the API answered, so this is not a verdict on `
425
+ return new CommandRefusalError('EXTERNAL_API_FAILED', `${error.message}\nThe connection closed before the API answered, so this is not a verdict on `
420
426
  + `the upload. VAT had sent ${formatBytes(error.bytesSent)} of a ${formatBytes(bodyBytes)} `
421
427
  + `request body against a ${formatBytes(API_SKILL_MAX_UPLOAD_BYTES)} ceiling; the API has `
422
428
  + 'been observed to drop a connection near that ceiling instead of returning 413. Whether '
@@ -463,9 +469,9 @@ export function resolveSourceArgument(source) {
463
469
  *
464
470
  * Not a limit on what may be PUBLISHED — the API's own ceiling decides that, and
465
471
  * a bigger document simply goes unread rather than refused. It bounds the
466
- * allocations this module performs on attacker-supplied metadata: `getData()`
467
- * inflates whatever `header.size` claims, and a header can claim anything. A
468
- * megabyte is two orders of magnitude above any real skill document.
472
+ * allocations this module performs on attacker-supplied metadata: reading an
473
+ * entry inflates up to the size its header claims, and a header can claim
474
+ * anything. A megabyte is two orders of magnitude above any real skill document.
469
475
  *
470
476
  * ⚠️ It is a PER-ENTRY bound. The total is bounded separately, and more
471
477
  * tightly: nothing is inflated at all until the archive's declared uncompressed
@@ -502,44 +508,69 @@ const MAX_INSPECTED_DOCUMENT_BYTES = 1024 * 1024;
502
508
  *
503
509
  * ⚠️ **Reading an entry is not free, and the docstring here used to claim it
504
510
  * was** — "no zip-slip or zip-bomb surface is opened — the entries are read, not
505
- * written" was true of the enumeration half and FALSE of the one `getData()`
506
- * call, which inflates `header.size` bytes into memory. Worse, it ran BEFORE the
511
+ * written" was true of the enumeration half and FALSE of the one read of an
512
+ * entry, which inflates up to its declared size into memory. Worse, it ran BEFORE the
507
513
  * caller's uncompressed-total gate, so the ceiling this function exists to
508
514
  * enforce could not protect the inflation this function performed. Nothing is
509
515
  * written to disk — that part stands — but the decompression is now ordered
510
516
  * after the total is known and bounded by {@link MAX_INSPECTED_DOCUMENT_BYTES},
511
517
  * so an archive declaring a 4 GiB SKILL.md is enumerated and never inflated.
518
+ *
519
+ * 🔑 **The archive is read through the ONE archive primitive, and held to its ONE
520
+ * entry policy.** An archive holding an entry VAT would refuse to extract — a
521
+ * symbolic link, a device, a name outside the archive, two entries that are one
522
+ * name (a name listed twice included) — or one past the archive limits, or one
523
+ * that is not a skill ZIP by the one layout rule (`requireSkillZipLayout`), is
524
+ * refused here (`INPUT_UNREADABLE`), before anything is sent: the same archive is
525
+ * refused by every verb that takes one. Only bytes the reader cannot PARSE as a
526
+ * ZIP at all are let through, announced (see the catch).
527
+ *
528
+ * @throws ArchiveRefusedError (`INPUT_UNREADABLE`) for an archive the entry policy
529
+ * or the archive limits refuse; FsFaultError side `source` when the OS refuses the read
512
530
  */
513
531
  export async function inspectZipArchive(zipPath) {
514
- // `adm-zip` is already a runtime dependency of this package (the packager and
515
- // the url skill-source both use it). An earlier comment here reasoned that
516
- // reading the archive would mean "adding a dependency … for a log line" and
517
- // declined on that basis; the premise was false, and the payoff is not a log
518
- // line but a refusal that saves a doomed upload of up to 30 MiB.
519
- const AdmZip = (await import('adm-zip')).default;
520
- let entries;
532
+ // Loaded on demand: the archive readers are needed by this one lane of the org commands.
533
+ const { ARCHIVE_LIMITS, archiveEntryRefusal, ArchiveRefusedError: Refused, openArchive, readArchiveFile, zipOfArchive } = await import('@vibe-agent-toolkit/utils/archive');
534
+ // Read ONCE: what is judged below, what is re-zipped and what an unreadable upload sends are these bytes.
535
+ const bytes = await readArchiveFile(zipPath, 'source', ARCHIVE_LIMITS);
536
+ const source = { bytes, label: toForwardSlash(zipPath) };
537
+ let opened;
521
538
  try {
522
- entries = new AdmZip(zipPath).getEntries();
539
+ opened = await openArchive(source, { format: 'zip', limits: ARCHIVE_LIMITS });
523
540
  }
524
541
  catch (error) {
525
- // An archive VAT cannot PARSE is not an archive VAT should block. The API
526
- // is the authority on the upload either way, and refusing here would turn
527
- // "our reader disagrees with your zip tool" into a failed publish. The
542
+ // Bytes that are no ZIP at all (`unreadable`: no ZIP signature anywhere) are
543
+ // not VAT's to block: the API is the authority on that upload, and the
528
544
  // caller is told why, so "checks skipped" is never silent.
529
545
  //
530
- // An archive the FILESYSTEM refuses is a different thing: the path was
531
- // readable a moment ago (the caller holds its bytes), so a refusal here
532
- // is not a parse disagreement and stays loud.
533
- if (isFilesystemAccessError(error))
534
- throw error;
535
- return { archiveUnreadable: describeZipFailure(error) };
546
+ // That is the ONLY reason let through. A ZIP VAT will not take
547
+ // (`unsupported`: ZIP64, an ambiguous end record, a directory two readers
548
+ // would read differently, an end record padded past the 64 KiB a reader
549
+ // searches) stays loud, like an archive past the limits — were it passed
550
+ // on, a 20-byte edit or a 64 KiB append to any refused ZIP would send it
551
+ // with every check skipped. So does one the FILESYSTEM refuses (the path
552
+ // was readable a moment ago — the caller holds its bytes).
553
+ if (isUnparseableArchive(error))
554
+ return { archiveUnreadable: error.message, bytes };
555
+ throw error;
536
556
  }
557
+ const refusal = archiveEntryRefusal(opened.entries);
558
+ if (refusal !== undefined)
559
+ throw new Refused(opened.label, refusal);
560
+ // The one layout rule for a skill ZIP, shared with the two install verbs: an archive that is
561
+ // not a skill by it is refused here, never sent for the API to make what it can of.
562
+ const skillRoot = requireSkillZipLayout(opened.label, opened.entries);
537
563
  // PASS 1 — headers only. Nothing is decompressed while this runs, so both
538
564
  // refusals the caller can reach are decided on metadata alone.
539
- const files = entries.filter(entry => !entry.isDirectory);
540
- const uncompressedBytes = files.reduce((sum, entry) => sum + entry.header.size, 0);
565
+ const hostAdded = opened.entries.map(entry => entry.name).filter(name => hostAddedToSkillZip(name));
566
+ const sent = {
567
+ fileBytes: bytes.length,
568
+ upload: () => zipOfArchive(source, { format: 'zip', limits: ARCHIVE_LIMITS, omit: (entry) => hostAddedToSkillZip(entry.name) }),
569
+ };
570
+ const files = opened.entries.filter(entry => entry.kind === 'file' && !hostAddedToSkillZip(entry.name));
571
+ const uncompressedBytes = files.reduce((sum, entry) => sum + entry.size, 0);
541
572
  const neverUploaded = files
542
- .map(entry => toForwardSlashAnyPlatform(entry.entryName))
573
+ .map(entry => toForwardSlashAnyPlatform(entry.name))
543
574
  .filter(name => name.split('/').some(segment => NEVER_UPLOADED_DIR_NAMES.has(segment)));
544
575
  // PASS 2 — the entries worth inflating, and only once the total says this
545
576
  // archive is not already refused. An over-ceiling archive is about to be
@@ -547,23 +578,25 @@ export async function inspectZipArchive(zipPath) {
547
578
  // on an upload that cannot happen.
548
579
  if (uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
549
580
  return {
550
- uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined, unreadable: [],
581
+ uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined, hostAdded, unreadable: [], ...sent,
551
582
  };
552
583
  }
553
- const elected = electShallowestSkillMd(files);
584
+ const elected = skillMdOf(files, skillRoot);
554
585
  const unreadable = [];
555
586
  return {
556
587
  uncompressedBytes,
557
- declaredName: declaredNameOf(elected, unreadable),
588
+ declaredName: declaredNameOf(opened, elected, unreadable),
558
589
  neverUploaded,
559
- documents: inflateMarkdownMembers(files, unreadable),
560
- bundleRoot: archiveRootOf(elected?.entryName),
590
+ documents: inflateMarkdownMembers(opened, files, unreadable),
591
+ bundleRoot: skillRoot === '' ? undefined : skillRoot,
592
+ hostAdded,
561
593
  unreadable,
594
+ ...sent,
562
595
  };
563
596
  }
564
- /** adm-zip throws plain `Error`s; the message is all it has to say. */
565
- function describeZipFailure(error) {
566
- return error instanceof Error ? error.message : String(error);
597
+ /** Whether `error` is the archive module saying the bytes are no ZIP at all — by its code and reason, never its prose. A ZIP it will not take, an entry that does not inflate included, is `unsupported`, and is not this. */
598
+ function isUnparseableArchive(error) {
599
+ return isVatError(error, ARCHIVE_REFUSED_CODE) && error.reason === 'unreadable';
567
600
  }
568
601
  /**
569
602
  * Every markdown member of the archive, as an upload part.
@@ -577,19 +610,19 @@ function describeZipFailure(error) {
577
610
  * {@link warnUnportableReferences} keeps ONE implementation of the checks — a
578
611
  * second copy of the three collector calls is how the two lanes start disagreeing.
579
612
  *
580
- * An entry that will not inflate is SKIPPED, never fatal: this module's standing
581
- * position is that an archive VAT cannot read is not an archive VAT should block,
582
- * and the checks it feeds only ever warn.
613
+ * An entry that will not inflate is SKIPPED here and named: the checks it feeds
614
+ * only ever warn. The upload is what refuses it — VAT sends its own ZIP of what
615
+ * it read, and it could not read this.
583
616
  */
584
- function inflateMarkdownMembers(files, unreadable) {
617
+ function inflateMarkdownMembers(archive, files, unreadable) {
585
618
  const documents = [];
586
619
  for (const entry of files) {
587
- const filename = toForwardSlashAnyPlatform(entry.entryName);
620
+ const filename = toForwardSlashAnyPlatform(entry.name);
588
621
  if (!filename.toLowerCase().endsWith('.md'))
589
622
  continue;
590
- if (entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
623
+ if (entry.size > MAX_INSPECTED_DOCUMENT_BYTES)
591
624
  continue;
592
- const content = inflateOrRecord(entry, unreadable);
625
+ const content = inflateOrRecord(archive, entry, unreadable);
593
626
  if (content !== undefined)
594
627
  documents.push({ fieldName: 'files[]', filename, content });
595
628
  }
@@ -598,87 +631,42 @@ function inflateMarkdownMembers(files, unreadable) {
598
631
  /**
599
632
  * One member's bytes, or `undefined` with the refusal RECORDED.
600
633
  *
601
- * `getData()` is the only decompression in this module, so it is the only thing
602
- * that can throw here: adm-zip raises on BAD_CRC, on any compression method but
603
- * store/deflate, and on an encrypted entry. Those used to escape and abort the
604
- * publish on exit 2 — contradicting this module's own stance that an archive VAT
605
- * cannot parse is not an archive VAT should block — and then, once caught, were
606
- * dropped without a word. The member is skipped AND named.
634
+ * Reading an entry is the only decompression in this module, so it is the only
635
+ * thing that can throw here: the archive module refuses an entry with a bad CRC,
636
+ * a compression method that is not store/deflate, an encrypted entry, or one
637
+ * that does not hold what it declares (`ArchiveEntryReadError`, `ARCHIVE_ENTRY_UNREADABLE`).
638
+ * The inspection skips the member AND names it, so every finding the other
639
+ * members earn is still reported; the archive is not thereby accepted — the
640
+ * upload re-reads every entry for VAT's own ZIP and refuses this one, so nothing
641
+ * is sent.
607
642
  */
608
- function inflateOrRecord(entry, unreadable) {
643
+ function inflateOrRecord(archive, entry, unreadable) {
609
644
  try {
610
- return entry.getData();
645
+ return archive.read(entry);
611
646
  }
612
647
  catch (error) {
648
+ if (!isArchiveEntryReadRefusal(error))
649
+ throw error;
613
650
  // Once per member: the elected SKILL.md is asked for twice (its name, then
614
651
  // its text), and one refusal is one fact.
615
- const name = toForwardSlashAnyPlatform(entry.entryName);
652
+ const name = toForwardSlashAnyPlatform(entry.name);
616
653
  if (!unreadable.some((failure) => failure.entry === name)) {
617
- unreadable.push({ entry: name, reason: describeZipFailure(error) });
654
+ unreadable.push({ entry: name, reason: error.message });
618
655
  }
619
656
  return undefined;
620
657
  }
621
658
  }
622
659
  /**
623
- * The directory the elected SKILL.md sits in, which is the archive's bundle root.
660
+ * The archive's own SKILL.md: the one at the place the layout rule found the skill
661
+ * (`requireSkillZipLayout`), which is the one whose `name` the API keys the skill by.
662
+ * Never a `SKILL.md` deeper in the bundle — a fixture a skill ships is not the skill.
624
663
  *
625
- * `my-skill/SKILL.md` roots the bundle at `my-skill`; a SKILL.md at the archive
626
- * root has no prefix, and neither does an archive with no SKILL.md at all. ZIP
627
- * fixes `/` as the entry separator, so this reads the format rather than handling
628
- * a host path.
664
+ * @param files - The archive's file entries
665
+ * @param root - Where the skill is: `''` for the archive's top level, or its one top-level folder
629
666
  */
630
- function archiveRootOf(entryName) {
631
- if (entryName === undefined)
632
- return undefined;
633
- const cut = toForwardSlashAnyPlatform(entryName).lastIndexOf('/');
634
- return cut === -1 ? undefined : entryName.slice(0, cut);
635
- }
636
- /**
637
- * The SKILL.md nearest the archive root, which is the one whose `name` the API
638
- * will key the skill by.
639
- *
640
- * 🪤 Compared on DEPTH, with name length only as a tiebreak. It used to compare
641
- * `entryName.length` alone, on the reasoning that "a shortest-path comparison
642
- * needs no separator at all" — but shortest string is not shallowest path:
643
- * `a/b/SKILL.md` (12 chars, depth 2) beats `my-skill-bundle/SKILL.md` (24
644
- * chars, depth 1), so a bundled FIXTURE supplied the name and the operator was
645
- * advised to `--title` it. ZIP fixes `/` as the entry separator on every
646
- * platform, so splitting on it is not path handling — it is reading the format.
647
- */
648
- function electShallowestSkillMd(files) {
649
- let elected;
650
- for (const entry of files) {
651
- if (basename(entry.entryName) !== 'SKILL.md')
652
- continue;
653
- if (elected !== undefined && !isShallower(entry.entryName, elected.entryName))
654
- continue;
655
- elected = entry;
656
- }
657
- return elected;
658
- }
659
- /** Fewer path segments wins; equal depth falls back to the shorter name. */
660
- function isShallower(candidate, incumbent) {
661
- const candidateDepth = zipEntryDepth(candidate);
662
- const incumbentDepth = zipEntryDepth(incumbent);
663
- return candidateDepth === incumbentDepth
664
- ? candidate.length < incumbent.length
665
- : candidateDepth < incumbentDepth;
666
- }
667
- /**
668
- * How many segments a ZIP entry name has.
669
- *
670
- * Counted rather than `split('/')`-ed because the linter — correctly, for
671
- * FILESYSTEM paths — refuses that idiom: a host path's separator depends on the
672
- * platform. A ZIP entry name's does not; the format fixes it as `/`. Counting
673
- * the separator states that, and needs no exemption.
674
- */
675
- function zipEntryDepth(entryName) {
676
- let depth = 1;
677
- for (const character of entryName) {
678
- if (character === '/')
679
- depth += 1;
680
- }
681
- return depth;
667
+ function skillMdOf(files, root) {
668
+ const place = root === '' ? 'SKILL.md' : `${root}/SKILL.md`;
669
+ return files.find(entry => archiveEntryPlace(entry.name).join('/') === place);
682
670
  }
683
671
  /**
684
672
  * The frontmatter `name` inside the ELECTED entry — or `undefined`, including
@@ -695,10 +683,10 @@ function zipEntryDepth(entryName) {
695
683
  * is already computed from headers) — see {@link inflateOrRecord}, which records
696
684
  * the refusal so the operator learns why no name was read.
697
685
  */
698
- function declaredNameOf(entry, unreadable) {
699
- if (entry === undefined || entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
686
+ function declaredNameOf(archive, entry, unreadable) {
687
+ if (entry === undefined || entry.size > MAX_INSPECTED_DOCUMENT_BYTES)
700
688
  return undefined;
701
- const content = inflateOrRecord(entry, unreadable);
689
+ const content = inflateOrRecord(archive, entry, unreadable);
702
690
  return content === undefined ? undefined : declaredSkillNameIn(content.toString('utf8'));
703
691
  }
704
692
  async function sendSkillUpload(client, displayTitle, files, bundleRoot) {
@@ -712,7 +700,7 @@ async function sendSkillUpload(client, displayTitle, files, bundleRoot) {
712
700
  function requireDeclaredName(skillMdPath) {
713
701
  const declared = readDeclaredSkillName(skillMdPath);
714
702
  if (declared === undefined) {
715
- throw new Error(`SKILL.md has no usable frontmatter "name" field: ${skillMdPath}`);
703
+ throw new CommandRefusalError('USAGE_INVALID', `SKILL.md has no usable frontmatter "name" field: ${skillMdPath}`);
716
704
  }
717
705
  return declared;
718
706
  }
@@ -757,19 +745,21 @@ async function declaredTestInputPaths(skillDir) {
757
745
  * named no path and said nothing about what to do. A dangling link produced the
758
746
  * same shape of failure with `ENOENT`.
759
747
  *
760
- * `statSync` follows the link, which is the same thing the build-time size walk
748
+ * `requireFollowedStatSync` follows the link (its chain read first), which is the same thing the build-time size walk
761
749
  * does to classify one — so both lanes reach the same verdict about the same
762
750
  * entry.
763
751
  */
764
- function resolvesToDirectory(entry, fullPath, relativePath) {
752
+ function resolvesToDirectory(entry, fullPath, relativePath, within) {
765
753
  if (!entry.isSymbolicLink())
766
754
  return false;
767
755
  try {
768
- return statSync(fullPath).isDirectory();
756
+ // The chain is read beneath the skill directory first: a link to a network path is refused
757
+ // here, by name, before the kernel is asked to follow it.
758
+ return requireFollowedStatSync(fullPath, within).isDirectory();
769
759
  }
770
760
  catch (error) {
771
761
  const cause = error instanceof Error ? error.message : String(error);
772
- throw new Error(`Cannot upload ${relativePath}: it is a symbolic link whose target could not be read `
762
+ throw new CommandRefusalError('INPUT_UNREADABLE', `Cannot upload ${relativePath}: it is a symbolic link whose target could not be read `
773
763
  + `(${cause}). Replace it with the file or directory it should point at, or remove it.`);
774
764
  }
775
765
  }
@@ -809,7 +799,7 @@ function collectFiles(dir, base, testInput, collected) {
809
799
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
810
800
  const fullPath = safePath.join(dir, entry.name);
811
801
  const relativePath = safePath.relative(base, fullPath);
812
- const linkedDirectory = resolvesToDirectory(entry, fullPath, relativePath);
802
+ const linkedDirectory = resolvesToDirectory(entry, fullPath, relativePath, base);
813
803
  const directoryLike = entry.isDirectory() || linkedDirectory;
814
804
  if (testInput.has(safePath.resolve(fullPath))
815
805
  || (directoryLike && NEVER_UPLOADED_DIR_NAMES.has(entry.name))) {
@@ -822,7 +812,7 @@ function collectFiles(dir, base, testInput, collected) {
822
812
  else if (entry.isSymbolicLink()) {
823
813
  // Whatever it points at. A link to a FILE used to fall through to the
824
814
  // branch below and be read through — see this function's doc comment.
825
- throw new Error(`Cannot upload ${relativePath}: it is a symbolic link${linkedDirectory ? ' to a directory' : ''}, `
815
+ throw new CommandRefusalError('INPUT_UNREADABLE', `Cannot upload ${relativePath}: it is a symbolic link${linkedDirectory ? ' to a directory' : ''}, `
826
816
  + 'which a multipart upload cannot express. VAT will not publish the bytes it points '
827
817
  + 'at under this name: a link out of the skill directory would send whatever the '
828
818
  + 'target holds into a workspace every org member can read. Replace it with a real '
@@ -844,6 +834,17 @@ export async function collectSkillUploadFiles(skillDir) {
844
834
  collectFiles(skillDir, skillDir, await declaredTestInputPaths(skillDir), collected);
845
835
  return collected;
846
836
  }
837
+ /**
838
+ * Stat a path the operator named, refusing through the one absent-vs-unreadable
839
+ * predicate: absent is the invocation's mistake (`USAGE_INVALID`, with this
840
+ * site's own sentence); anything else — an `EACCES` parent, an `ELOOP` — means
841
+ * whether it exists is unknown, the INPUT's refusal (`INPUT_UNREADABLE`).
842
+ * Never `existsSync`: it answers `false` for both.
843
+ */
844
+ function statNamedPath(path, within, absentMessage) {
845
+ // Every path from the operator's named tree down to it is the operator's input.
846
+ return requireInputPath(path, within, { origin: 'argument', message: absentMessage }, everywhere('source'));
847
+ }
847
848
  /**
848
849
  * Package a skill directory into the multipart file set the API takes.
849
850
  *
@@ -855,9 +856,7 @@ export async function collectSkillUploadFiles(skillDir) {
855
856
  */
856
857
  async function prepareSkillUpload(skillDir, titleOverride, logger) {
857
858
  const skillMdPath = safePath.join(skillDir, 'SKILL.md');
858
- if (!existsSync(skillMdPath)) {
859
- throw new Error(`SKILL.md not found in ${skillDir}. Is this a built skill directory?`);
860
- }
859
+ statNamedPath(skillMdPath, skillDir, `SKILL.md not found in ${skillDir}. Is this a built skill directory?`);
861
860
  // The skill's own declared name — not the directory it happens to sit in,
862
861
  // which for a built or extracted tree carries no reliable identity.
863
862
  const declaredName = requireDeclaredName(skillMdPath);
@@ -1019,19 +1018,19 @@ async function uploadSkillVersionDir(client, skillId, skillDir, logger) {
1019
1018
  * untested — `packages/cli/src/commands/**` is coverage-excluded, so nothing in
1020
1019
  * any report said so.
1021
1020
  */
1022
- export function listNodeModulePackages(nodeModulesDir) {
1023
- if (!existsSync(nodeModulesDir))
1021
+ export function listNodeModulePackages(nodeModulesDir, within) {
1022
+ if (!pathPresent(nodeModulesDir, { follow: within }, everywhere('source'), 'probe'))
1024
1023
  return [];
1025
1024
  const results = [];
1026
1025
  // Followed: a workspace package under node_modules IS a symlink, and a walk
1027
1026
  // that tested `isDirectory()` on the link skipped every one of them.
1028
1027
  for (const entry of readdirSync(nodeModulesDir, { withFileTypes: true })) {
1029
- if (direntKindFollowingSync(nodeModulesDir, entry) !== 'directory')
1028
+ if (direntKindFollowingSync(nodeModulesDir, entry, within) !== 'directory')
1030
1029
  continue;
1031
1030
  if (entry.name.startsWith('@')) {
1032
1031
  const scopeDir = safePath.join(nodeModulesDir, entry.name);
1033
1032
  for (const scopedEntry of readdirSync(scopeDir, { withFileTypes: true })) {
1034
- if (direntKindFollowingSync(scopeDir, scopedEntry) === 'directory')
1033
+ if (direntKindFollowingSync(scopeDir, scopedEntry, within) === 'directory')
1035
1034
  results.push(safePath.join(scopeDir, scopedEntry.name));
1036
1035
  }
1037
1036
  }
@@ -1046,17 +1045,27 @@ export function listNodeModulePackages(nodeModulesDir) {
1046
1045
  * first, then scans node_modules for sub-packages that contain built skills.
1047
1046
  */
1048
1047
  export function findSkillsDir(packageDir) {
1048
+ // Every probe is beneath the package directory: its links are read before the kernel follows them,
1049
+ // and a probe the OS refuses is the package's source fault, never "no skills here".
1050
+ const present = (path) => pathPresent(path, { follow: packageDir }, everywhere('source'), 'probe');
1049
1051
  const direct = safePath.join(packageDir, 'dist', 'skills');
1050
- if (existsSync(direct))
1052
+ if (present(direct))
1051
1053
  return direct;
1052
- const candidates = listNodeModulePackages(safePath.join(packageDir, 'node_modules'));
1054
+ const candidates = listNodeModulePackages(safePath.join(packageDir, 'node_modules'), packageDir);
1053
1055
  for (const pkgDir of candidates) {
1054
1056
  const candidate = safePath.join(pkgDir, 'dist', 'skills');
1055
- if (existsSync(candidate))
1057
+ if (present(candidate))
1056
1058
  return candidate;
1057
1059
  }
1058
1060
  return undefined;
1059
1061
  }
1062
+ /**
1063
+ * The failure row for one skill, coded by the thrown value exactly as a run-level
1064
+ * refusal would be. Exported for testing.
1065
+ */
1066
+ export function skillUploadFailure(skill, error) {
1067
+ return { skill, error: { code: refusalCodeOf(error), message: errorMessageOf(error) } };
1068
+ }
1060
1069
  /**
1061
1070
  * The batch's report, tagged as a failure when ANY skill did not publish.
1062
1071
  *
@@ -1073,79 +1082,83 @@ export function findSkillsDir(packageDir) {
1073
1082
  * the same lie, only smaller. What did land stays in the document, so the reader
1074
1083
  * can see how far the run got.
1075
1084
  */
1076
- export function summarizeNpmInstall(source, results, errors) {
1085
+ export function summarizeNpmInstall(source, results, errors, leftover) {
1077
1086
  const summary = {
1078
1087
  source,
1079
1088
  skillsUploaded: results.length,
1080
1089
  ...(errors.length > 0 ? { skillsFailed: errors.length, errors } : {}),
1081
1090
  skills: results,
1091
+ ...(leftover === undefined ? {} : { warnings: [leftoverIssueOf(leftover)] }),
1082
1092
  };
1083
- return errors.length > 0 ? orgCommandFailure(summary) : summary;
1093
+ if (errors.length === 0)
1094
+ return summary;
1095
+ // Some landed: the workspace is in a mixed state (`partial`). None did: `failed`.
1096
+ return orgCommandFailure(summary, results.length > 0
1097
+ ? { kind: 'partial', failed: errors.length }
1098
+ : { kind: 'failed', cause: `no skill from ${source} uploaded` });
1084
1099
  }
1085
1100
  /**
1086
- * Upload skills from an npm package.
1101
+ * Upload skills from an npm package. Exported for testing.
1087
1102
  */
1088
- async function installFromNpm(npmPackage, skillFilter, client, logger) {
1089
- const tempDir = mkdtempSync(safePath.join(normalizedTmpdir(), 'vat-org-skills-'));
1090
- try {
1103
+ export async function installFromNpm(npmPackage, skillFilter, client, logger) {
1104
+ // The download lives in a temp dir disposed of however the upload ends. One the OS will not
1105
+ // remove after the uploads is reported beside them, never in their place: they landed.
1106
+ const { value, leftover } = await withTempDir('vat-org-skills-', async (tempDir) => {
1091
1107
  logger.info(`Downloading: ${npmPackage}`);
1092
- const packageDir = downloadNpmPackage(npmPackage, tempDir);
1108
+ const packageDir = await downloadNpmPackage(npmPackage, tempDir);
1093
1109
  const skillsDir = findSkillsDir(packageDir);
1094
1110
  if (!skillsDir) {
1095
- throw new Error(`No dist/skills/ directory found in ${npmPackage}. Was the package built with vat skills build?`);
1111
+ throw new CommandRefusalError('USAGE_INVALID', `No dist/skills/ directory found in ${npmPackage}. Was the package built with vat skills build?`);
1096
1112
  }
1097
1113
  logger.info(`Found skills at: ${safePath.relative(packageDir, skillsDir) || 'dist/skills/'}`);
1098
1114
  // Followed: a built skill directory that is a link is still a skill to upload.
1099
1115
  const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
1100
- .filter(e => direntKindFollowingSync(skillsDir, e) === 'directory')
1116
+ .filter(e => direntKindFollowingSync(skillsDir, e, packageDir) === 'directory')
1101
1117
  .map(e => e.name);
1102
1118
  if (skillDirs.length === 0) {
1103
- throw new Error(`No skills found in dist/skills/ of ${npmPackage}`);
1119
+ throw new CommandRefusalError('USAGE_INVALID', `No skills found in dist/skills/ of ${npmPackage}`);
1104
1120
  }
1105
1121
  const toUpload = skillFilter
1106
1122
  ? skillDirs.filter(name => name === skillFilter)
1107
1123
  : skillDirs;
1108
1124
  if (toUpload.length === 0) {
1109
- throw new Error(`Skill "${String(skillFilter)}" not found in ${npmPackage}. Available: ${skillDirs.join(', ')}`);
1125
+ throw new CommandRefusalError('USAGE_INVALID', `Skill "${String(skillFilter)}" not found in ${npmPackage}. Available: ${skillDirs.join(', ')}`);
1110
1126
  }
1111
1127
  logger.info(`Found ${toUpload.length} skill(s) to upload from ${npmPackage}`);
1112
1128
  const results = [];
1113
1129
  const errors = [];
1114
- for (const skillName of toUpload) {
1130
+ // In order: one rate-limited API, and the result and failure lists follow `toUpload`.
1131
+ await forEachInOrder(toUpload, async (skillName) => {
1115
1132
  const skillDir = safePath.join(skillsDir, skillName);
1116
1133
  try {
1117
1134
  const result = await uploadSkillDir(client, skillDir, undefined, logger);
1118
1135
  results.push(result);
1119
1136
  }
1120
1137
  catch (error) {
1121
- const msg = error instanceof Error ? error.message : String(error);
1122
- logger.info(` ⚠ ${skillName}: ${msg}`);
1123
- errors.push({ skill: skillName, error: msg });
1138
+ const failure = skillUploadFailure(skillName, error);
1139
+ logger.info(` ⚠ ${skillName}: ${failure.error.message}`);
1140
+ errors.push(failure);
1124
1141
  }
1125
- }
1126
- return summarizeNpmInstall(npmPackage, results, errors);
1127
- }
1128
- finally {
1129
- rmSync(tempDir, { recursive: true, force: true });
1130
- }
1142
+ });
1143
+ return { results, errors };
1144
+ });
1145
+ return summarizeNpmInstall(npmPackage, value.results, value.errors, leftover);
1131
1146
  }
1132
1147
  /**
1133
1148
  * Upload a local skill directory or ZIP file. Exported for testing.
1134
1149
  */
1135
1150
  export async function installFromLocal(source, titleOverride, client, logger) {
1136
1151
  const sourcePath = resolveSourceArgument(source);
1137
- if (!existsSync(sourcePath)) {
1138
- throw new Error(`Source not found: ${sourcePath}`);
1139
- }
1140
- const stat = statSync(sourcePath);
1152
+ // The operator's own argument: its own `within`.
1153
+ const stat = statNamedPath(sourcePath, sourcePath, `Source not found: ${sourcePath}`);
1141
1154
  // Case-INSENSITIVE. `endsWith('.zip')` refused `MySkill.ZIP` as "not a directory
1142
1155
  // or .zip file" — a file Windows and macOS both consider a zip archive, and one
1143
1156
  // an operator has no way to read that refusal as being about capitalisation.
1144
1157
  if (!stat.isDirectory() && sourcePath.toLowerCase().endsWith('.zip')) {
1145
- return installZipArchive(sourcePath, titleOverride, client, logger);
1158
+ return await installZipArchive(sourcePath, titleOverride, client, logger);
1146
1159
  }
1147
1160
  if (!stat.isDirectory()) {
1148
- throw new Error(`Source must be a directory or .zip file: ${sourcePath}`);
1161
+ throw new CommandRefusalError('USAGE_INVALID', `Source must be a directory or .zip file: ${sourcePath}`);
1149
1162
  }
1150
1163
  // "Packaging", not "Uploading". Everything that follows this line — reading the
1151
1164
  // config, collecting the file set, weighing the request — happens locally and
@@ -1156,7 +1169,7 @@ export async function installFromLocal(source, titleOverride, client, logger) {
1156
1169
  // all — `--from-npm` packages several skills in a loop, and a packaging error
1157
1170
  // with no path above it names nothing.
1158
1171
  logger.info(`Packaging skill directory: ${sourcePath}`);
1159
- return uploadSkillDir(client, sourcePath, titleOverride, logger);
1172
+ return await uploadSkillDir(client, sourcePath, titleOverride, logger);
1160
1173
  }
1161
1174
  /**
1162
1175
  * Publish a ZIP archive as a NEW skill.
@@ -1171,12 +1184,9 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
1171
1184
  // `basename(path, ext)` matches the extension exactly, so the literal '.zip'
1172
1185
  // leaves `.ZIP` on the title. Slice the length instead.
1173
1186
  const displayTitle = titleOverride ?? basename(sourcePath).slice(0, -'.zip'.length);
1174
- const zipContent = readFileSync(sourcePath);
1175
- const files = [{
1176
- fieldName: 'files[]',
1177
- filename: basename(sourcePath),
1178
- content: zipContent,
1179
- }];
1187
+ // The ONE read of the file: everything below is decided on, and sent from, what this read.
1188
+ const inspected = await inspectZipArchive(sourcePath);
1189
+ const fileBytes = 'archiveUnreadable' in inspected ? inspected.bytes.length : inspected.fileBytes;
1180
1190
  // A ZIP is by construction a single large binary, so this is the shape most
1181
1191
  // likely to be over the ceiling — and the one that reached the wire unmeasured
1182
1192
  // while the check lived only in the directory-packaging path. It is gated in
@@ -1186,37 +1196,34 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
1186
1196
  // "Preparing", not "Uploading": nothing has been sent at this point, and the
1187
1197
  // very next step can refuse locally. A line that claims an upload started is
1188
1198
  // the log telling the operator about work that never happened.
1189
- logger.info(`Preparing ZIP: ${sourcePath} (${formatBytes(zipContent.length)} of file content)`);
1199
+ logger.info(`Preparing ZIP: ${sourcePath} (${formatBytes(fileBytes)} of file content)`);
1190
1200
  // Where the title came FROM, not just what it is. A ZIP's title is the
1191
1201
  // filename — `wiki-lint-v2.zip` publishes a skill called `wiki-lint-v2`,
1192
1202
  // which is a DIFFERENT skill from `wiki-lint` and is not refused, because
1193
1203
  // display_title uniqueness is enforced only when the field is sent. A
1194
1204
  // directory takes its title from SKILL.md instead, so the same tree zipped
1195
- // and unzipped can publish under two names.
1196
- //
1197
- // ⛔ This comment used to end "VAT cannot read the SKILL.md inside the
1198
- // archive: Node ships no ZIP reader, and adding a dependency to parse one
1199
- // here would mean owning central-directory, zip64 and zip-slip handling for
1200
- // a log line." The PREMISE was false — `adm-zip` is already a runtime
1201
- // dependency of this package — and the cost/benefit was weighed against the
1202
- // wrong benefit: the same read also answers whether the archive EXPANDS
1203
- // past the ceiling, which is a refusal, not a log line. So the archive is
1204
- // now read (see {@link inspectZipArchive}) and the divergence is reported
1205
- // as a fact below, in addition to this provenance line.
1205
+ // and unzipped can publish under two names — the inspection reads the name
1206
+ // the archive's SKILL.md declares, and the divergence is reported below.
1206
1207
  logger.info(`Display title: "${displayTitle}" (${titleOverride === undefined
1207
1208
  ? 'from the ZIP filename — NOT from the SKILL.md inside it; pass --title to set it'
1208
1209
  : 'from --title'})`);
1209
- const inspected = await inspectZipArchive(sourcePath);
1210
+ let content;
1210
1211
  if ('archiveUnreadable' in inspected) {
1211
1212
  // Degrade, and SAY so. Every check below is skipped, and a skipped check
1212
1213
  // that is not announced is indistinguishable from one that passed.
1213
1214
  logger.warn(`Could not read the archive (${inspected.archiveUnreadable}); the answer-key, expanded-size, `
1214
1215
  + `name and portability checks were not run on it. The API decides the upload.`);
1216
+ content = inspected.bytes;
1215
1217
  }
1216
1218
  else {
1217
- refuseOrWarnOnArchive(inspected, displayTitle, zipContent.length, logger);
1219
+ refuseOrWarnOnArchive(inspected, displayTitle, fileBytes, logger);
1220
+ if (inspected.hostAdded.length > 0) {
1221
+ logger.info(`Left out of the upload (added by the host that made the archive, not part of the skill): ${inspected.hostAdded.join(', ')}`);
1222
+ }
1223
+ // What is sent is what was judged: VAT's own ZIP of the entries it read, never the operator's bytes.
1224
+ content = await inspected.upload();
1218
1225
  }
1219
- return sendSkillUpload(client, displayTitle, files);
1226
+ return sendSkillUpload(client, displayTitle, [{ fieldName: 'files[]', filename: basename(sourcePath), content }]);
1220
1227
  }
1221
1228
  /**
1222
1229
  * The archive lane's own decisions, over what {@link inspectZipArchive} read:
@@ -1239,7 +1246,7 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
1239
1246
  // unreadable here. That is a narrower check than the directory lane's,
1240
1247
  // not a looser verdict on what it does see.
1241
1248
  if (inspected.neverUploaded.length > 0) {
1242
- throw new Error(`This ZIP contains ${String(inspected.neverUploaded.length)} entr`
1249
+ throw new CommandRefusalError('USAGE_INVALID', `This ZIP contains ${String(inspected.neverUploaded.length)} entr`
1243
1250
  + `${inspected.neverUploaded.length === 1 ? 'y' : 'ies'} that are never published with a `
1244
1251
  + `skill: ${inspected.neverUploaded.slice(0, 10).join(', ')}`
1245
1252
  + `${inspected.neverUploaded.length > 10 ? ', …' : ''}. An eval suite is the skill's ANSWER `
@@ -1248,7 +1255,7 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
1248
1255
  + `\`install <dir>\` withholds these and reports each one.`);
1249
1256
  }
1250
1257
  if (inspected.uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
1251
- throw new Error(`ZIP expands to ${formatBytes(inspected.uncompressedBytes)}, over the `
1258
+ throw new CommandRefusalError('USAGE_INVALID', `ZIP expands to ${formatBytes(inspected.uncompressedBytes)}, over the `
1252
1259
  + `${formatBytes(API_SKILL_MAX_UPLOAD_BYTES)} ceiling. The API expands the archive and `
1253
1260
  + `weighs the UNCOMPRESSED total, so ${formatBytes(wireBytes)} on the wire does not `
1254
1261
  + `get this under the limit — it will refuse with "Zip file uncompressed size exceeds 30MB". `
@@ -1284,8 +1291,8 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
1284
1291
  warnUnportableReferences(inspected.documents, inspected.bundleRoot, undefined, logger);
1285
1292
  if (inspected.unreadable.length > 0) {
1286
1293
  const named = inspected.unreadable.map(({ entry, reason }) => `${entry} (${reason})`).join(', ');
1287
- logger.warn(`${String(inspected.unreadable.length)} archive member(s) could not be inflated and were `
1288
- + `not checked: ${named}`);
1294
+ logger.warn(`${String(inspected.unreadable.length)} archive member(s) could not be inflated: ${named}. `
1295
+ + 'They were not checked, and the upload will refuse the archive when it re-reads them — nothing is sent.');
1289
1296
  }
1290
1297
  }
1291
1298
  /**
@@ -1300,9 +1307,9 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
1300
1307
  * 2 of 30 hid the state of the other 28.
1301
1308
  *
1302
1309
  * The sweep therefore ATTEMPTS all of them and reports both lists. The caller
1303
- * decides what the outcome means: some deleted plus some failed is a run that
1304
- * happened and went wrong (exit 1, with the record); nothing deleted at all is
1305
- * the ending the command's help documents as exit 2.
1310
+ * decides what the outcome means: some deleted plus some failed is a `partial`
1311
+ * write that publishes the record; nothing deleted at all is a refusal with no
1312
+ * record worth publishing. Both end on 2.
1306
1313
  *
1307
1314
  * ⛔ It deliberately does NOT stop early on a repeated failure. A "the API is
1308
1315
  * clearly down, give up" heuristic is how the abandoned-versions defect reads
@@ -1312,7 +1319,8 @@ function refuseOrWarnOnArchive(inspected, displayTitle, wireBytes, logger) {
1312
1319
  export async function deleteEveryVersion(client, skillId, versions, logger) {
1313
1320
  const deleted = [];
1314
1321
  const failures = [];
1315
- for (const version of versions) {
1322
+ // In order: one rate-limited API, and both lists follow the order versions were handed in.
1323
+ await forEachInOrder(versions, async (version) => {
1316
1324
  try {
1317
1325
  await client.deleteSkillVersion(skillId, version);
1318
1326
  }
@@ -1320,16 +1328,16 @@ export async function deleteEveryVersion(client, skillId, versions, logger) {
1320
1328
  const reason = error instanceof Error ? error.message : String(error);
1321
1329
  failures.push({ version, reason });
1322
1330
  logger.info(` ⚠ version ${version} was not deleted: ${reason}`);
1323
- continue;
1331
+ return;
1324
1332
  }
1325
1333
  deleted.push(version);
1326
1334
  logger.info(` Deleted version ${version}`);
1327
- }
1335
+ });
1328
1336
  return { deleted, failures };
1329
1337
  }
1330
1338
  /**
1331
1339
  * Every version the sweep could not delete, and why — the one sentence both the
1332
- * published report and the exit-2 throw are built from, so the two endings never
1340
+ * published report and the refusal's throw are built from, so the two endings never
1333
1341
  * describe the same run differently.
1334
1342
  */
1335
1343
  export function describeVersionSweepFailures(failures) {
@@ -1341,10 +1349,10 @@ export function describeVersionSweepFailures(failures) {
1341
1349
  *
1342
1350
  * 🔑 The deleted list is a RECORD, not a progress counter. Version deletion is
1343
1351
  * irreversible, so a failure part-way through leaves a workspace nobody can
1344
- * reconstruct — and throwing here would end on `handleCommandError`'s exit 2
1345
- * ("the run could not happen") and DISCARD the document. It happened, and it
1346
- * destroyed things the operator now has no other list of. So the lists travel
1347
- * with the failure and the run ends 1: it happened, and its outcome is wrong.
1352
+ * reconstruct — and throwing here would publish only the refusal and DISCARD
1353
+ * the document. It happened, and it destroyed things the operator now has no
1354
+ * other list of. So the lists travel with the failure as a `partial` outcome:
1355
+ * the payload is published, and the adapter ends the run on 2.
1348
1356
  *
1349
1357
  * `failedVersions` is the other half, and the half a re-run needs: what is still
1350
1358
  * there. Without it the operator knows what they lost and not what they still
@@ -1352,17 +1360,20 @@ export function describeVersionSweepFailures(failures) {
1352
1360
  */
1353
1361
  export function reportHalfDeleted(report) {
1354
1362
  const { skillId, deletedVersions, failedVersions } = report;
1363
+ // Some writes landed (the deleted versions) and some did not: every version
1364
+ // still there, plus the skill itself, which is never deleted on this path.
1365
+ const outcome = { kind: 'partial', failed: failedVersions.length + 1 };
1355
1366
  return orgCommandFailure({
1356
1367
  id: skillId,
1357
1368
  deleted: false,
1358
1369
  deletedVersions,
1359
1370
  failedVersions,
1360
- error: report.error,
1371
+ reason: report.reason,
1361
1372
  note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted and cannot be `
1362
1373
  + `restored; ${String(failedVersions.length)} could not be deleted and are still there. `
1363
1374
  + 'The skill itself still exists — the API refuses a skill that still has versions. '
1364
1375
  + 'Re-run `--all` once the cause is cleared: it will attempt only what is left.',
1365
- });
1376
+ }, outcome);
1366
1377
  }
1367
1378
  // ── Commands ───────────────────────────────────────────────────────────
1368
1379
  export function createOrgSkillsCommand() {
@@ -1376,7 +1387,7 @@ export function createOrgSkillsCommand() {
1376
1387
  .description('List organization skills')
1377
1388
  .option('--debug', DEBUG_OPT_DESC)
1378
1389
  .action(async (options) => {
1379
- await executeOrgCommand('OrgSkillsList', options.debug, async ({ client }) => {
1390
+ await executeOrgCommand('claude org skills list', options.debug, ({ client }) => {
1380
1391
  return autopaginateSkills(client, '/v1/skills');
1381
1392
  });
1382
1393
  })
@@ -1399,8 +1410,7 @@ Example:
1399
1410
  .option('--title <title>', 'Display title override (single skill only)')
1400
1411
  .option('--debug', DEBUG_OPT_DESC)
1401
1412
  .action(async (source, options) => {
1402
- const commandName = options.fromNpm ? 'OrgSkillsInstallNpm' : 'OrgSkillsInstall';
1403
- await executeOrgCommand(commandName, options.debug, async ({ client, logger }) => {
1413
+ await executeOrgCommand('claude org skills install', options.debug, ({ client, logger }) => {
1404
1414
  // INSIDE the action, like `versions add`'s own guards. Thrown from the
1405
1415
  // Commander handler instead, these were a floating rejection that
1406
1416
  // reached no catch: Node printed a raw stack trace with absolute $HOME
@@ -1408,22 +1418,22 @@ Example:
1408
1418
  // exited 1 — which the documented contract reads as "at least one
1409
1419
  // error-severity finding" for a run in which nothing executed.
1410
1420
  if (!source && !options.fromNpm) {
1411
- throw new Error('Provide a <source> path or use --from-npm <package>');
1421
+ throw new CommandRefusalError('USAGE_INVALID', 'Provide a <source> path or use --from-npm <package>');
1412
1422
  }
1413
1423
  if (source && options.fromNpm) {
1414
- throw new Error('Provide either <source> or --from-npm, not both');
1424
+ throw new CommandRefusalError('USAGE_INVALID', 'Provide either <source> or --from-npm, not both');
1415
1425
  }
1416
1426
  // The other two illegal combinations, refused rather than dropped. Both
1417
1427
  // flags used to be accepted and silently ignored on the lane that cannot
1418
1428
  // honour them, which is how an operator gets a skill published under the
1419
1429
  // wrong title — or every skill in a package published when they named one.
1420
1430
  if (options.title !== undefined && options.fromNpm) {
1421
- throw new Error('--title applies to a single skill and --from-npm can publish several, so it is '
1431
+ throw new CommandRefusalError('USAGE_INVALID', '--title applies to a single skill and --from-npm can publish several, so it is '
1422
1432
  + 'refused here rather than silently ignored. Publish the one skill with '
1423
1433
  + '--skill and set its title in its SKILL.md, or upload its directory directly.');
1424
1434
  }
1425
1435
  if (options.skill !== undefined && !options.fromNpm) {
1426
- throw new Error('--skill selects one skill inside an npm package; it applies only with --from-npm');
1436
+ throw new CommandRefusalError('USAGE_INVALID', '--skill selects one skill inside an npm package; it applies only with --from-npm');
1427
1437
  }
1428
1438
  if (options.fromNpm) {
1429
1439
  return installFromNpm(options.fromNpm, options.skill, client, logger);
@@ -1442,10 +1452,27 @@ Description:
1442
1452
 
1443
1453
  A ZIP takes its display_title from the ZIP FILENAME, so my-skill-v2.zip
1444
1454
  publishes a skill titled "my-skill-v2", which is a separate skill from
1445
- "my-skill" and is not refused as a duplicate. VAT reads the SKILL.md nearest
1446
- the root of the archive and WARNS when the name it declares differs from that
1447
- title, because every version the skill ever gets will carry the declared name.
1448
- Pass --title to set the title explicitly.
1455
+ "my-skill" and is not refused as a duplicate. VAT reads the archive's SKILL.md
1456
+ and WARNS when the name it declares differs from that title, because every
1457
+ version the skill ever gets will carry the declared name. Pass --title to set
1458
+ the title explicitly.
1459
+
1460
+ A ZIP holds SKILL.md at its top level, or exactly one top-level folder with
1461
+ SKILL.md directly inside (a skill folder, compressed) — the layout the install
1462
+ verbs take. Any other layout is refused (INPUT_UNREADABLE), and so is a ZIP
1463
+ holding a symbolic link, a name that leaves the archive, one name twice, or
1464
+ more than 50,000 entries / 256 MiB expanded, a name Windows cannot hold (a
1465
+ ":", < > " | ? *, a control character, a device name such as CON or aux.md,
1466
+ a trailing "." or space), a ZIP64 archive, one whose end record two readers
1467
+ could read differently or is not in its last 64 KiB, one with data before its
1468
+ first local header (a self-extracting ZIP) or a directory entry whose local
1469
+ header is not its own, or one holding an entry VAT cannot inflate. What is
1470
+ sent is VAT's own ZIP of the entries it read and checked (its names, order,
1471
+ timestamps, compression and 0644/0755 modes) — never your file's bytes — so a
1472
+ top-level __MACOSX/ folder or .DS_Store (what macOS adds) is left out.
1473
+ Only bytes that are no ZIP at all (no local-file-header or end-record
1474
+ signature anywhere in them) are sent as they are, with a warning that the
1475
+ checks below were skipped.
1449
1476
 
1450
1477
  A skill's eval suite is its answer key and is never uploaded: whatever the
1451
1478
  governing vibe-agent-toolkit.config.yaml declares as this skill's test input
@@ -1494,9 +1521,10 @@ Description:
1494
1521
 
1495
1522
  Exit Codes:
1496
1523
  0 - Every skill uploaded
1497
- 1 - The run completed and at least one skill failed to upload (--from-npm
1498
- uploads several; the ones that landed are listed under skills)
1499
- 2 - The run could not happen: no API key, no such source, unusable input
1524
+ 2 - At least one skill failed to upload (--from-npm uploads several; the ones
1525
+ that landed are still listed under skills, each failure under errors as
1526
+ { skill, error: { code, message } }), or the run was refused: no
1527
+ API key, no such source, unusable input ({ error: { code, message } })
1500
1528
 
1501
1529
  Examples:
1502
1530
  $ vat claude org skills install dist/skills/org-admin
@@ -1512,23 +1540,22 @@ Examples:
1512
1540
  .option('--all', 'Auto-delete all versions before deleting the skill')
1513
1541
  .option('--debug', DEBUG_OPT_DESC)
1514
1542
  .action(async (skillId, options) => {
1515
- await executeOrgCommand('OrgSkillsDelete', options.debug, async ({ client, logger }) => {
1543
+ await executeOrgCommand('claude org skills delete', options.debug, async ({ client, logger }) => {
1516
1544
  // Every version this run actually destroyed, accumulated as it goes.
1517
1545
  //
1518
1546
  // 🔑 It is a RECORD, not a progress counter. Version deletion is
1519
1547
  // irreversible and `--all` does it in a loop, so a failure part-way
1520
1548
  // through leaves a workspace nobody can reconstruct — and the old code
1521
- // threw at that point, which ends on `handleCommandError`'s exit 2
1522
- // ("the run could not happen") and DISCARDS the document. It happened,
1523
- // and it destroyed things the operator now has no list of. So the list
1524
- // travels with the failure, and the run ends 1: it happened, and its
1525
- // outcome is wrong.
1549
+ // threw at that point, which publishes only the refusal and DISCARDS
1550
+ // the document. It happened, and it destroyed things the operator now
1551
+ // has no list of. So the list travels with the failure as a `partial`
1552
+ // outcome: published, and ending on 2.
1526
1553
  const deletedVersions = [];
1527
1554
  const halfDeleted = (error, failedVersions) => reportHalfDeleted({
1528
1555
  skillId,
1529
1556
  deletedVersions,
1530
1557
  failedVersions,
1531
- error: error instanceof Error ? error.message : String(error),
1558
+ reason: errorMessageOf(error),
1532
1559
  });
1533
1560
  if (options.all) {
1534
1561
  const versions = await autopaginateSkills(client, skillVersionsPath(skillId));
@@ -1544,11 +1571,11 @@ Examples:
1544
1571
  if (sweep.failures.length > 0) {
1545
1572
  const detail = describeVersionSweepFailures(sweep.failures);
1546
1573
  // Nothing was destroyed, so there is no record worth publishing and
1547
- // "could not happen" (exit 2, via the throw) is the honest ending —
1574
+ // the refusal (EXTERNAL_API_FAILED, exit 2, via the throw) is the honest ending —
1548
1575
  // the same rule as before, now decided on the WHOLE sweep rather than
1549
1576
  // on its first refusal.
1550
1577
  if (deletedVersions.length === 0) {
1551
- throw new Error(`No version of ${skillId} could be deleted, so the skill was left alone. `
1578
+ throw new CommandRefusalError('EXTERNAL_API_FAILED', `No version of ${skillId} could be deleted, so the skill was left alone. `
1552
1579
  + `${String(sweep.failures.length)} attempt(s) failed — ${detail}`);
1553
1580
  }
1554
1581
  // The skill delete is not attempted: the API refuses a skill that still
@@ -1594,10 +1621,11 @@ Description:
1594
1621
  --all deletes irreversibly and in a loop, and it ATTEMPTS EVERY VERSION even
1595
1622
  when one refuses — one refusal is a fact about one version, not about the ones
1596
1623
  after it. When the sweep ends with anything left, the versions it destroyed are
1597
- listed under deletedVersions, the ones still there under failedVersions, and
1598
- the run exits 1 — the run happened, and its outcome is wrong. The skill itself
1624
+ listed under deletedVersions, the ones still there under failedVersions, why
1625
+ under reason, and the run exits 2 with that record published. The skill itself
1599
1626
  is then left alone, because the API refuses a skill that still has versions.
1600
- It exits 2 only when nothing was deleted at all.
1627
+ When nothing was deleted at all, it publishes only the refusal
1628
+ ({ error: { code, message } }), also at 2.
1601
1629
 
1602
1630
  A version delete whose response is lost is replayed, and the replay is answered
1603
1631
  404 because the first attempt already removed it. That 404 is read as the
@@ -1605,10 +1633,10 @@ Description:
1605
1633
 
1606
1634
  Exit Codes:
1607
1635
  0 - The skill was deleted
1608
- 1 - The run completed and the skill was NOT deleted: the API named a different
1609
- outcome, or --all destroyed some versions and could not destroy the rest
1610
- 2 - The run could not happen: no API key, the first request was refused, or
1611
- --all deleted no version at all
1636
+ 2 - The skill was NOT deleted: the API named a different outcome, or --all
1637
+ destroyed some versions and could not destroy the rest (the document
1638
+ lists both); or the run was refused — no API key, the first request was
1639
+ refused, or --all deleted no version at all ({ error: { code, message } })
1612
1640
 
1613
1641
  Example:
1614
1642
  $ vat claude org skills delete skill_abc123 --all
@@ -1622,7 +1650,7 @@ Example:
1622
1650
  .argument(SKILL_ID_ARG, SKILL_ID_DESC)
1623
1651
  .option('--debug', DEBUG_OPT_DESC)
1624
1652
  .action(async (skillId, options) => {
1625
- await executeOrgCommand('OrgSkillsVersionsList', options.debug, async ({ client }) => {
1653
+ await executeOrgCommand('claude org skills versions list', options.debug, ({ client }) => {
1626
1654
  return autopaginateSkills(client, skillVersionsPath(skillId));
1627
1655
  });
1628
1656
  })
@@ -1641,7 +1669,7 @@ Example:
1641
1669
  .argument('<version>', 'Version to delete')
1642
1670
  .option('--debug', DEBUG_OPT_DESC)
1643
1671
  .action(async (skillId, version, options) => {
1644
- await executeOrgCommand('OrgSkillsVersionsDelete', options.debug, async ({ client, logger }) => {
1672
+ await executeOrgCommand('claude org skills versions delete', options.debug, async ({ client, logger }) => {
1645
1673
  logger.info(`Deleting version ${version} of skill ${skillId}`);
1646
1674
  return reportVersionDelete(await client.deleteSkillVersion(skillId, version), skillId, version);
1647
1675
  });
@@ -1659,8 +1687,8 @@ Output:
1659
1687
 
1660
1688
  Exit Codes:
1661
1689
  0 - The version was deleted
1662
- 1 - The run completed and the API named an outcome other than a deletion
1663
- 2 - The run could not happen: no API key, or the request was refused
1690
+ 2 - The API named an outcome other than a deletion, or the run was refused:
1691
+ no API key, or the request was refused ({ error: { code, message } })
1664
1692
 
1665
1693
  Example:
1666
1694
  $ vat claude org skills versions delete skill_abc123 1775007400733130
@@ -1678,11 +1706,9 @@ Example:
1678
1706
  .argument('<source>', 'Path to a built skill directory')
1679
1707
  .option('--debug', DEBUG_OPT_DESC)
1680
1708
  .action(async (skillId, source, options) => {
1681
- await executeOrgCommand('OrgSkillsVersionsAdd', options.debug, async ({ client, logger }) => {
1709
+ await executeOrgCommand('claude org skills versions add', options.debug, ({ client, logger }) => {
1682
1710
  const resolved = resolveSourceArgument(source);
1683
- if (!existsSync(resolved))
1684
- throw new Error(`Source not found: ${resolved}`);
1685
- if (!statSync(resolved).isDirectory()) {
1711
+ if (!statNamedPath(resolved, resolved, `Source not found: ${resolved}`).isDirectory()) {
1686
1712
  // Name the asymmetry IN the refusal, not only in --help. `install`
1687
1713
  // accepts a ZIP and this verb does not, so the operator most likely to
1688
1714
  // hit this is the one who just read that `install` takes one — and a
@@ -1692,7 +1718,7 @@ Example:
1692
1718
  ? ' A ZIP is accepted by `vat claude org skills install`, not here:'
1693
1719
  + ' publish a new version from the built skill directory instead.'
1694
1720
  : '';
1695
- throw new Error(`Source must be a skill directory: ${resolved}.${zipHint}`);
1721
+ throw new CommandRefusalError('USAGE_INVALID', `Source must be a skill directory: ${resolved}.${zipHint}`);
1696
1722
  }
1697
1723
  // "Packaging", not "Publishing" — see `installFromLocal`. Measured: this
1698
1724
  // line printed, then `Failed to load config: …`, and nothing had been
@@ -1731,7 +1757,8 @@ Description:
1731
1757
 
1732
1758
  Exit Codes:
1733
1759
  0 - The version was published
1734
- 2 - The run could not happen: no API key, no such source, not a directory,
1760
+ 2 - The run was refused ({ error: { code, message } }): no API key, no such
1761
+ source, not a directory,
1735
1762
  over the upload ceiling, or a response the version identifier
1736
1763
  cannot be read from
1737
1764