@vibe-agent-toolkit/cli 0.2.0-rc.6 → 0.2.0-rc.7

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 (194) hide show
  1. package/README.md +4 -4
  2. package/dist/bin.js +41 -158
  3. package/dist/bin.js.map +1 -1
  4. package/dist/command-loaders.d.ts +2 -2
  5. package/dist/command-loaders.d.ts.map +1 -1
  6. package/dist/command-loaders.js +4 -2
  7. package/dist/command-loaders.js.map +1 -1
  8. package/dist/commands/ard/emit.d.ts +104 -0
  9. package/dist/commands/ard/emit.d.ts.map +1 -0
  10. package/dist/commands/ard/emit.js +223 -0
  11. package/dist/commands/ard/emit.js.map +1 -0
  12. package/dist/commands/ard/index.d.ts +12 -0
  13. package/dist/commands/ard/index.d.ts.map +1 -0
  14. package/dist/commands/ard/index.js +79 -0
  15. package/dist/commands/ard/index.js.map +1 -0
  16. package/dist/commands/ard/surfaces.d.ts +56 -0
  17. package/dist/commands/ard/surfaces.d.ts.map +1 -0
  18. package/dist/commands/ard/surfaces.js +150 -0
  19. package/dist/commands/ard/surfaces.js.map +1 -0
  20. package/dist/commands/audit.d.ts +75 -8
  21. package/dist/commands/audit.d.ts.map +1 -1
  22. package/dist/commands/audit.js +605 -140
  23. package/dist/commands/audit.js.map +1 -1
  24. package/dist/commands/claude/budget.d.ts +13 -0
  25. package/dist/commands/claude/budget.d.ts.map +1 -1
  26. package/dist/commands/claude/budget.js +80 -28
  27. package/dist/commands/claude/budget.js.map +1 -1
  28. package/dist/commands/claude/context.js +1 -1
  29. package/dist/commands/claude/context.js.map +1 -1
  30. package/dist/commands/claude/marketplace/validate.d.ts +55 -22
  31. package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
  32. package/dist/commands/claude/marketplace/validate.js +380 -75
  33. package/dist/commands/claude/marketplace/validate.js.map +1 -1
  34. package/dist/commands/claude/org/skills.d.ts +84 -3
  35. package/dist/commands/claude/org/skills.d.ts.map +1 -1
  36. package/dist/commands/claude/org/skills.js +218 -46
  37. package/dist/commands/claude/org/skills.js.map +1 -1
  38. package/dist/commands/claude/plugin/build.d.ts +8 -0
  39. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  40. package/dist/commands/claude/plugin/build.js +16 -2
  41. package/dist/commands/claude/plugin/build.js.map +1 -1
  42. package/dist/commands/claude/plugin/tree-copy.d.ts +72 -0
  43. package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
  44. package/dist/commands/claude/plugin/tree-copy.js +215 -10
  45. package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
  46. package/dist/commands/corpus/index.d.ts.map +1 -1
  47. package/dist/commands/corpus/index.js +3 -0
  48. package/dist/commands/corpus/index.js.map +1 -1
  49. package/dist/commands/corpus/report.d.ts +0 -1
  50. package/dist/commands/corpus/report.d.ts.map +1 -1
  51. package/dist/commands/corpus/report.js +0 -1
  52. package/dist/commands/corpus/report.js.map +1 -1
  53. package/dist/commands/corpus/runner.d.ts +58 -1
  54. package/dist/commands/corpus/runner.d.ts.map +1 -1
  55. package/dist/commands/corpus/runner.js +90 -15
  56. package/dist/commands/corpus/runner.js.map +1 -1
  57. package/dist/commands/corpus/scan.d.ts.map +1 -1
  58. package/dist/commands/corpus/scan.js +0 -1
  59. package/dist/commands/corpus/scan.js.map +1 -1
  60. package/dist/commands/doctor.d.ts +14 -0
  61. package/dist/commands/doctor.d.ts.map +1 -1
  62. package/dist/commands/doctor.js +96 -18
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/okf/index.d.ts +11 -0
  65. package/dist/commands/okf/index.d.ts.map +1 -0
  66. package/dist/commands/okf/index.js +102 -0
  67. package/dist/commands/okf/index.js.map +1 -0
  68. package/dist/commands/okf/validate.d.ts +82 -0
  69. package/dist/commands/okf/validate.d.ts.map +1 -0
  70. package/dist/commands/okf/validate.js +157 -0
  71. package/dist/commands/okf/validate.js.map +1 -0
  72. package/dist/commands/phase-utils.d.ts +19 -3
  73. package/dist/commands/phase-utils.d.ts.map +1 -1
  74. package/dist/commands/phase-utils.js +26 -5
  75. package/dist/commands/phase-utils.js.map +1 -1
  76. package/dist/commands/rag/index-command.d.ts +27 -2
  77. package/dist/commands/rag/index-command.d.ts.map +1 -1
  78. package/dist/commands/rag/index-command.js +44 -7
  79. package/dist/commands/rag/index-command.js.map +1 -1
  80. package/dist/commands/rag/index.d.ts.map +1 -1
  81. package/dist/commands/rag/index.js +2 -0
  82. package/dist/commands/rag/index.js.map +1 -1
  83. package/dist/commands/resources/check-progress.d.ts +3 -0
  84. package/dist/commands/resources/check-progress.d.ts.map +1 -1
  85. package/dist/commands/resources/check-progress.js +6 -0
  86. package/dist/commands/resources/check-progress.js.map +1 -1
  87. package/dist/commands/resources/check.d.ts +33 -4
  88. package/dist/commands/resources/check.d.ts.map +1 -1
  89. package/dist/commands/resources/check.js +131 -44
  90. package/dist/commands/resources/check.js.map +1 -1
  91. package/dist/commands/resources/index.d.ts.map +1 -1
  92. package/dist/commands/resources/index.js +41 -9
  93. package/dist/commands/resources/index.js.map +1 -1
  94. package/dist/commands/resources/query.d.ts +18 -1
  95. package/dist/commands/resources/query.d.ts.map +1 -1
  96. package/dist/commands/resources/query.js +29 -4
  97. package/dist/commands/resources/query.js.map +1 -1
  98. package/dist/commands/resources/validate.d.ts +29 -0
  99. package/dist/commands/resources/validate.d.ts.map +1 -1
  100. package/dist/commands/resources/validate.js +116 -13
  101. package/dist/commands/resources/validate.js.map +1 -1
  102. package/dist/commands/skill/review.d.ts.map +1 -1
  103. package/dist/commands/skill/review.js +9 -2
  104. package/dist/commands/skill/review.js.map +1 -1
  105. package/dist/commands/skill/test/run.d.ts.map +1 -1
  106. package/dist/commands/skill/test/run.js +21 -6
  107. package/dist/commands/skill/test/run.js.map +1 -1
  108. package/dist/commands/skills/build.d.ts.map +1 -1
  109. package/dist/commands/skills/build.js +16 -3
  110. package/dist/commands/skills/build.js.map +1 -1
  111. package/dist/commands/skills/list.d.ts +2 -1
  112. package/dist/commands/skills/list.d.ts.map +1 -1
  113. package/dist/commands/skills/list.js +31 -9
  114. package/dist/commands/skills/list.js.map +1 -1
  115. package/dist/commands/skills/skill-discovery.d.ts +40 -1
  116. package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
  117. package/dist/commands/skills/skill-discovery.js +32 -3
  118. package/dist/commands/skills/skill-discovery.js.map +1 -1
  119. package/dist/commands/skills/validate-command.d.ts.map +1 -1
  120. package/dist/commands/skills/validate-command.js +11 -3
  121. package/dist/commands/skills/validate-command.js.map +1 -1
  122. package/dist/commands/skills/validate.d.ts +66 -7
  123. package/dist/commands/skills/validate.d.ts.map +1 -1
  124. package/dist/commands/skills/validate.js +133 -29
  125. package/dist/commands/skills/validate.js.map +1 -1
  126. package/dist/commands/verify.d.ts +94 -3
  127. package/dist/commands/verify.d.ts.map +1 -1
  128. package/dist/commands/verify.js +192 -45
  129. package/dist/commands/verify.js.map +1 -1
  130. package/dist/skill-resolution/packaging-config.d.ts +49 -5
  131. package/dist/skill-resolution/packaging-config.d.ts.map +1 -1
  132. package/dist/skill-resolution/packaging-config.js +59 -19
  133. package/dist/skill-resolution/packaging-config.js.map +1 -1
  134. package/dist/skill-resolution/resolve-skill-reference.d.ts.map +1 -1
  135. package/dist/skill-resolution/resolve-skill-reference.js +6 -3
  136. package/dist/skill-resolution/resolve-skill-reference.js.map +1 -1
  137. package/dist/utils/command-error.d.ts +31 -0
  138. package/dist/utils/command-error.d.ts.map +1 -1
  139. package/dist/utils/command-error.js +45 -0
  140. package/dist/utils/command-error.js.map +1 -1
  141. package/dist/utils/edge-lens-evaluation.d.ts +83 -0
  142. package/dist/utils/edge-lens-evaluation.d.ts.map +1 -0
  143. package/dist/utils/edge-lens-evaluation.js +110 -0
  144. package/dist/utils/edge-lens-evaluation.js.map +1 -0
  145. package/dist/utils/optional-backend.d.ts +5 -4
  146. package/dist/utils/optional-backend.d.ts.map +1 -1
  147. package/dist/utils/optional-backend.js +5 -4
  148. package/dist/utils/optional-backend.js.map +1 -1
  149. package/dist/utils/project-root-policy.d.ts +20 -0
  150. package/dist/utils/project-root-policy.d.ts.map +1 -1
  151. package/dist/utils/project-root-policy.js +32 -0
  152. package/dist/utils/project-root-policy.js.map +1 -1
  153. package/dist/utils/projection-query.d.ts +41 -4
  154. package/dist/utils/projection-query.d.ts.map +1 -1
  155. package/dist/utils/projection-query.js +44 -10
  156. package/dist/utils/projection-query.js.map +1 -1
  157. package/dist/utils/projection-store.d.ts +41 -15
  158. package/dist/utils/projection-store.d.ts.map +1 -1
  159. package/dist/utils/projection-store.js +65 -18
  160. package/dist/utils/projection-store.js.map +1 -1
  161. package/dist/utils/repeatable-option.d.ts +37 -0
  162. package/dist/utils/repeatable-option.d.ts.map +1 -0
  163. package/dist/utils/repeatable-option.js +39 -0
  164. package/dist/utils/repeatable-option.js.map +1 -0
  165. package/dist/utils/resource-loader.d.ts +4 -3
  166. package/dist/utils/resource-loader.d.ts.map +1 -1
  167. package/dist/utils/resource-loader.js +61 -30
  168. package/dist/utils/resource-loader.js.map +1 -1
  169. package/dist/utils/root-argv.d.ts +53 -0
  170. package/dist/utils/root-argv.d.ts.map +1 -0
  171. package/dist/utils/root-argv.js +215 -0
  172. package/dist/utils/root-argv.js.map +1 -0
  173. package/dist/utils/run-integrity.d.ts +95 -0
  174. package/dist/utils/run-integrity.d.ts.map +1 -0
  175. package/dist/utils/run-integrity.js +102 -0
  176. package/dist/utils/run-integrity.js.map +1 -0
  177. package/dist/utils/sqlite-experimental-warning.d.ts +69 -0
  178. package/dist/utils/sqlite-experimental-warning.d.ts.map +1 -0
  179. package/dist/utils/sqlite-experimental-warning.js +144 -0
  180. package/dist/utils/sqlite-experimental-warning.js.map +1 -0
  181. package/dist/utils/user-context-scanner.d.ts +8 -0
  182. package/dist/utils/user-context-scanner.d.ts.map +1 -1
  183. package/dist/utils/user-context-scanner.js +4 -0
  184. package/dist/utils/user-context-scanner.js.map +1 -1
  185. package/dist/utils/validate-help-files.d.ts.map +1 -1
  186. package/dist/utils/validate-help-files.js +9 -2
  187. package/dist/utils/validate-help-files.js.map +1 -1
  188. package/docs/audit.md +120 -7
  189. package/docs/doctor.md +6 -6
  190. package/docs/index.md +1 -1
  191. package/docs/rag.md +3 -1
  192. package/docs/resources.md +5 -1
  193. package/docs/skills.md +47 -62
  194. package/package.json +18 -18
@@ -296,11 +296,28 @@ export interface ZipInspection {
296
296
  * ZIP lane reach the same verdict about the same content.
297
297
  */
298
298
  readonly neverUploaded: readonly string[];
299
+ /**
300
+ * Every markdown member, inflated, shaped as the parts the directory lane
301
+ * hands {@link warnUnportableReferences} — so the ZIP lane runs the SAME
302
+ * checks over the same content rather than a second implementation of them.
303
+ *
304
+ * Markdown only, and only within {@link MAX_INSPECTED_DOCUMENT_BYTES} an
305
+ * entry: these detectors read prose, and inflating an archive's binaries to
306
+ * hand them to a reader that skips them is work spent to produce nothing.
307
+ */
308
+ readonly documents: readonly MultipartFile[];
309
+ /**
310
+ * The archive's top-level directory, when it has one — the prefix
311
+ * {@link bundleRelativeName} strips so a finding is located in the same
312
+ * namespace a `validation.allow` glob is matched in. `undefined` for an
313
+ * archive whose SKILL.md sits at the root, which has no prefix to strip.
314
+ */
315
+ readonly bundleRoot: string | undefined;
299
316
  }
300
317
  /**
301
318
  * What a ZIP will weigh AFTER the API expands it, read from the archive's own
302
- * central directory — plus the name its inner SKILL.md declares, and any answer
303
- * key it carries.
319
+ * central directory — plus the name its inner SKILL.md declares, any answer key
320
+ * it carries, and the markdown members the portability checks read.
304
321
  *
305
322
  * 🔑 **The API expands a ZIP and applies the ceiling to the UNCOMPRESSED total,
306
323
  * not to the archive.** Measured against the live API by an adopter: a
@@ -332,7 +349,7 @@ export interface ZipInspection {
332
349
  * caller's uncompressed-total gate, so the ceiling this function exists to
333
350
  * enforce could not protect the inflation this function performed. Nothing is
334
351
  * written to disk — that part stands — but the decompression is now ordered
335
- * after the total is known and bounded by {@link MAX_INSPECTED_SKILL_MD_BYTES},
352
+ * after the total is known and bounded by {@link MAX_INSPECTED_DOCUMENT_BYTES},
336
353
  * so an archive declaring a 4 GiB SKILL.md is enumerated and never inflated.
337
354
  */
338
355
  export declare function inspectZipArchive(zipPath: string): Promise<ZipInspection | undefined>;
@@ -447,6 +464,70 @@ export declare function summarizeNpmInstall(source: string, results: readonly Sk
447
464
  * Upload a local skill directory or ZIP file. Exported for testing.
448
465
  */
449
466
  export declare function installFromLocal(source: string, titleOverride: string | undefined, client: OrgApiClient, logger: UploadLogger): Promise<object>;
467
+ /** One version the sweep could not delete, and the reason it gave. */
468
+ export interface VersionDeleteFailure {
469
+ readonly version: string;
470
+ readonly reason: string;
471
+ }
472
+ /** What a `--all` sweep did to the versions it was handed. */
473
+ export interface VersionSweep {
474
+ /** Versions this run destroyed. Irreversible, and the record of it. */
475
+ readonly deleted: readonly string[];
476
+ /** Versions still there, each with why. Empty means the sweep is complete. */
477
+ readonly failures: readonly VersionDeleteFailure[];
478
+ }
479
+ /**
480
+ * Delete every version handed in, and keep going when one refuses.
481
+ *
482
+ * 🚨 **One refusal is a fact about ONE version.** This loop used to return on the
483
+ * first one, so every version after it was never ATTEMPTED — not failed, not
484
+ * reported, unexamined. Deleting a workspace skill requires deleting every
485
+ * version first, so the operator was left with a skill that could not be deleted,
486
+ * a report that named one problem out of an unknown number, and no way to tell
487
+ * from the output which versions were still there. A transient refusal on version
488
+ * 2 of 30 hid the state of the other 28.
489
+ *
490
+ * The sweep therefore ATTEMPTS all of them and reports both lists. The caller
491
+ * decides what the outcome means: some deleted plus some failed is a run that
492
+ * happened and went wrong (exit 1, with the record); nothing deleted at all is
493
+ * the ending the command's help documents as exit 2.
494
+ *
495
+ * ⛔ It deliberately does NOT stop early on a repeated failure. A "the API is
496
+ * clearly down, give up" heuristic is how the abandoned-versions defect reads
497
+ * from inside: the whole value here is that every version's state is KNOWN when
498
+ * the command ends.
499
+ */
500
+ export declare function deleteEveryVersion(client: Pick<OrgApiClient, 'deleteSkillVersion'>, skillId: string, versions: readonly string[], logger: UploadLogger): Promise<VersionSweep>;
501
+ /**
502
+ * Every version the sweep could not delete, and why — the one sentence both the
503
+ * published report and the exit-2 throw are built from, so the two endings never
504
+ * describe the same run differently.
505
+ */
506
+ export declare function describeVersionSweepFailures(failures: readonly VersionDeleteFailure[]): string;
507
+ /** What {@link reportHalfDeleted} needs to describe a run that destroyed some of what it was asked to. */
508
+ export interface HalfDeletedReport {
509
+ readonly skillId: string;
510
+ readonly deletedVersions: readonly string[];
511
+ /** Versions still present. Empty when the sweep completed and the SKILL delete is what failed. */
512
+ readonly failedVersions: readonly string[];
513
+ readonly error: string;
514
+ }
515
+ /**
516
+ * The document a `--all` run publishes when it destroyed something and then did
517
+ * not finish.
518
+ *
519
+ * 🔑 The deleted list is a RECORD, not a progress counter. Version deletion is
520
+ * irreversible, so a failure part-way through leaves a workspace nobody can
521
+ * reconstruct — and throwing here would end on `handleCommandError`'s exit 2
522
+ * ("the run could not happen") and DISCARD the document. It happened, and it
523
+ * destroyed things the operator now has no other list of. So the lists travel
524
+ * with the failure and the run ends 1: it happened, and its outcome is wrong.
525
+ *
526
+ * `failedVersions` is the other half, and the half a re-run needs: what is still
527
+ * there. Without it the operator knows what they lost and not what they still
528
+ * have to deal with.
529
+ */
530
+ export declare function reportHalfDeleted(report: HalfDeletedReport): OrgCommandFailure;
450
531
  export declare function createOrgSkillsCommand(): Command;
451
532
  export {};
452
533
  //# sourceMappingURL=skills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/org/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/org/skills.ts"],"names":[],"mappings":"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"}
@@ -459,19 +459,23 @@ export function resolveSourceArgument(source) {
459
459
  : safePath.resolve(process.cwd(), source);
460
460
  }
461
461
  /**
462
- * The largest SKILL.md this will decompress to read a `name` out of.
462
+ * The largest single markdown member this will decompress to read.
463
463
  *
464
464
  * Not a limit on what may be PUBLISHED — the API's own ceiling decides that, and
465
- * a bigger document simply goes unread rather than refused. It bounds the one
466
- * allocation this module performs on attacker-supplied metadata: `getData()`
465
+ * a bigger document simply goes unread rather than refused. It bounds the
466
+ * allocations this module performs on attacker-supplied metadata: `getData()`
467
467
  * inflates whatever `header.size` claims, and a header can claim anything. A
468
- * megabyte is two orders of magnitude above any real SKILL.md.
468
+ * megabyte is two orders of magnitude above any real skill document.
469
+ *
470
+ * ⚠️ It is a PER-ENTRY bound. The total is bounded separately, and more
471
+ * tightly: nothing is inflated at all until the archive's declared uncompressed
472
+ * total is known to be within {@link API_SKILL_MAX_UPLOAD_BYTES}.
469
473
  */
470
- const MAX_INSPECTED_SKILL_MD_BYTES = 1024 * 1024;
474
+ const MAX_INSPECTED_DOCUMENT_BYTES = 1024 * 1024;
471
475
  /**
472
476
  * What a ZIP will weigh AFTER the API expands it, read from the archive's own
473
- * central directory — plus the name its inner SKILL.md declares, and any answer
474
- * key it carries.
477
+ * central directory — plus the name its inner SKILL.md declares, any answer key
478
+ * it carries, and the markdown members the portability checks read.
475
479
  *
476
480
  * 🔑 **The API expands a ZIP and applies the ceiling to the UNCOMPRESSED total,
477
481
  * not to the archive.** Measured against the live API by an adopter: a
@@ -503,7 +507,7 @@ const MAX_INSPECTED_SKILL_MD_BYTES = 1024 * 1024;
503
507
  * caller's uncompressed-total gate, so the ceiling this function exists to
504
508
  * enforce could not protect the inflation this function performed. Nothing is
505
509
  * written to disk — that part stands — but the decompression is now ordered
506
- * after the total is known and bounded by {@link MAX_INSPECTED_SKILL_MD_BYTES},
510
+ * after the total is known and bounded by {@link MAX_INSPECTED_DOCUMENT_BYTES},
507
511
  * so an archive declaring a 4 GiB SKILL.md is enumerated and never inflated.
508
512
  */
509
513
  export async function inspectZipArchive(zipPath) {
@@ -530,14 +534,68 @@ export async function inspectZipArchive(zipPath) {
530
534
  const neverUploaded = files
531
535
  .map(entry => toForwardSlash(entry.entryName))
532
536
  .filter(name => name.split('/').some(segment => NEVER_UPLOADED_DIR_NAMES.has(segment)));
533
- // PASS 2 — the ONE entry worth inflating, and only once the total says this
537
+ // PASS 2 — the entries worth inflating, and only once the total says this
534
538
  // archive is not already refused. An over-ceiling archive is about to be
535
539
  // rejected by the caller, so inflating anything out of it would be work spent
536
540
  // on an upload that cannot happen.
537
- const declaredName = uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES
538
- ? undefined
539
- : declaredNameOf(electShallowestSkillMd(files));
540
- return { uncompressedBytes, declaredName, neverUploaded };
541
+ if (uncompressedBytes > API_SKILL_MAX_UPLOAD_BYTES) {
542
+ return { uncompressedBytes, declaredName: undefined, neverUploaded, documents: [], bundleRoot: undefined };
543
+ }
544
+ const elected = electShallowestSkillMd(files);
545
+ return {
546
+ uncompressedBytes,
547
+ declaredName: declaredNameOf(elected),
548
+ neverUploaded,
549
+ documents: inflateMarkdownMembers(files),
550
+ bundleRoot: archiveRootOf(elected?.entryName),
551
+ };
552
+ }
553
+ /**
554
+ * Every markdown member of the archive, as an upload part.
555
+ *
556
+ * 🔑 This exists so the ZIP lane can run the portability family through the ONE
557
+ * function the directory lane runs it through. Until it did, `install <zip>`
558
+ * performed none of the checks `install --help` promises of "every markdown
559
+ * document in the bundle": the archive went to `sendSkillUpload` as one opaque
560
+ * part, and an operator following the documented contract got silence where they
561
+ * were promised warnings. Routing the parts back through
562
+ * {@link warnUnportableReferences} keeps ONE implementation of the checks — a
563
+ * second copy of the three collector calls is how the two lanes start disagreeing.
564
+ *
565
+ * An entry that will not inflate is SKIPPED, never fatal: this module's standing
566
+ * position is that an archive VAT cannot read is not an archive VAT should block,
567
+ * and the checks it feeds only ever warn.
568
+ */
569
+ function inflateMarkdownMembers(files) {
570
+ const documents = [];
571
+ for (const entry of files) {
572
+ const filename = toForwardSlash(entry.entryName);
573
+ if (!filename.toLowerCase().endsWith('.md'))
574
+ continue;
575
+ if (entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
576
+ continue;
577
+ try {
578
+ documents.push({ fieldName: 'files[]', filename, content: entry.getData() });
579
+ }
580
+ catch {
581
+ continue;
582
+ }
583
+ }
584
+ return documents;
585
+ }
586
+ /**
587
+ * The directory the elected SKILL.md sits in, which is the archive's bundle root.
588
+ *
589
+ * `my-skill/SKILL.md` roots the bundle at `my-skill`; a SKILL.md at the archive
590
+ * root has no prefix, and neither does an archive with no SKILL.md at all. ZIP
591
+ * fixes `/` as the entry separator, so this reads the format rather than handling
592
+ * a host path.
593
+ */
594
+ function archiveRootOf(entryName) {
595
+ if (entryName === undefined)
596
+ return undefined;
597
+ const cut = toForwardSlash(entryName).lastIndexOf('/');
598
+ return cut === -1 ? undefined : entryName.slice(0, cut);
541
599
  }
542
600
  /**
543
601
  * The SKILL.md nearest the archive root, which is the one whose `name` the API
@@ -605,7 +663,7 @@ function zipEntryDepth(entryName) {
605
663
  * computed from headers, so failing here costs only the name.
606
664
  */
607
665
  function declaredNameOf(entry) {
608
- if (entry === undefined || entry.header.size > MAX_INSPECTED_SKILL_MD_BYTES)
666
+ if (entry === undefined || entry.header.size > MAX_INSPECTED_DOCUMENT_BYTES)
609
667
  return undefined;
610
668
  try {
611
669
  return declaredSkillNameIn(entry.getData().toString('utf8'));
@@ -650,7 +708,10 @@ function requireDeclaredName(skillMdPath) {
650
708
  * skill dir — nothing inside the tree to withhold.
651
709
  */
652
710
  async function declaredTestInputPaths(skillDir) {
653
- const config = await resolveSkillPackagingConfig(safePath.join(skillDir, 'SKILL.md'));
711
+ // `'refuse'`: an upload that cannot tell which paths are test input might
712
+ // publish an answer key. The throw is reported per skill by the install
713
+ // loop's catch (logged, and counted in its failures) — never swallowed.
714
+ const config = await resolveSkillPackagingConfig(safePath.join(skillDir, 'SKILL.md'), 'refuse');
654
715
  const declared = config?.test?.evals;
655
716
  if (declared === undefined)
656
717
  return new Set();
@@ -805,7 +866,7 @@ async function prepareSkillUpload(skillDir, titleOverride, logger) {
805
866
  // Resolved HERE rather than plumbed out of `collectSkillUploadFiles`, which is
806
867
  // exported and deliberately resolves its own so no caller can hand it a config
807
868
  // with the exclusion skipped.
808
- const packaging = await resolveSkillPackagingConfig(skillMdPath);
869
+ const packaging = await resolveSkillPackagingConfig(skillMdPath, 'refuse');
809
870
  warnUnportableReferences(files, dirName, packaging?.validation, logger);
810
871
  return { displayTitle, files, dirName };
811
872
  }
@@ -1169,9 +1230,102 @@ async function installZipArchive(sourcePath, titleOverride, client, logger) {
1169
1230
  + `SKILL.md inside declares name "${inspected.declaredName}". Every version will carry `
1170
1231
  + `the declared name. Pass --title "${inspected.declaredName}" to make them agree.`);
1171
1232
  }
1233
+ // 🚨 The SAME function the directory lane calls, over the archive's own
1234
+ // markdown. Until this line existed, `install <zip>` ran NONE of the
1235
+ // portability checks its `--help` promises of "every markdown document in
1236
+ // the bundle" — the archive went straight to `sendSkillUpload`, so the
1237
+ // adopter finding that produced the family (10 of 54 skills referencing a
1238
+ // path outside their own tree, published green and unable to run) was
1239
+ // invisible on the lane most likely to carry a hand-built bundle.
1240
+ //
1241
+ // ⚠️ NO validation config, and that is a real narrowing, stated in the
1242
+ // help text. `validation.allow` / `validation.severity` are resolved by
1243
+ // walking up from a skill's SKILL.md to its governing project — and an
1244
+ // archive member has no path on disk to walk up from, the same reason a
1245
+ // config-declared eval-suite location is unreadable here. So a waiver that
1246
+ // silences `vat skills build` does NOT silence this lane. The checks only
1247
+ // warn, so the cost of the narrowing is noise, never a blocked publish;
1248
+ // the cost of skipping them was silence on a documented promise.
1249
+ warnUnportableReferences(inspected.documents, inspected.bundleRoot, undefined, logger);
1172
1250
  }
1173
1251
  return sendSkillUpload(client, displayTitle, files);
1174
1252
  }
1253
+ /**
1254
+ * Delete every version handed in, and keep going when one refuses.
1255
+ *
1256
+ * 🚨 **One refusal is a fact about ONE version.** This loop used to return on the
1257
+ * first one, so every version after it was never ATTEMPTED — not failed, not
1258
+ * reported, unexamined. Deleting a workspace skill requires deleting every
1259
+ * version first, so the operator was left with a skill that could not be deleted,
1260
+ * a report that named one problem out of an unknown number, and no way to tell
1261
+ * from the output which versions were still there. A transient refusal on version
1262
+ * 2 of 30 hid the state of the other 28.
1263
+ *
1264
+ * The sweep therefore ATTEMPTS all of them and reports both lists. The caller
1265
+ * decides what the outcome means: some deleted plus some failed is a run that
1266
+ * happened and went wrong (exit 1, with the record); nothing deleted at all is
1267
+ * the ending the command's help documents as exit 2.
1268
+ *
1269
+ * ⛔ It deliberately does NOT stop early on a repeated failure. A "the API is
1270
+ * clearly down, give up" heuristic is how the abandoned-versions defect reads
1271
+ * from inside: the whole value here is that every version's state is KNOWN when
1272
+ * the command ends.
1273
+ */
1274
+ export async function deleteEveryVersion(client, skillId, versions, logger) {
1275
+ const deleted = [];
1276
+ const failures = [];
1277
+ for (const version of versions) {
1278
+ try {
1279
+ await client.deleteSkillVersion(skillId, version);
1280
+ }
1281
+ catch (error) {
1282
+ const reason = error instanceof Error ? error.message : String(error);
1283
+ failures.push({ version, reason });
1284
+ logger.info(` ⚠ version ${version} was not deleted: ${reason}`);
1285
+ continue;
1286
+ }
1287
+ deleted.push(version);
1288
+ logger.info(` Deleted version ${version}`);
1289
+ }
1290
+ return { deleted, failures };
1291
+ }
1292
+ /**
1293
+ * Every version the sweep could not delete, and why — the one sentence both the
1294
+ * published report and the exit-2 throw are built from, so the two endings never
1295
+ * describe the same run differently.
1296
+ */
1297
+ export function describeVersionSweepFailures(failures) {
1298
+ return failures.map(failure => `${failure.version}: ${failure.reason}`).join('; ');
1299
+ }
1300
+ /**
1301
+ * The document a `--all` run publishes when it destroyed something and then did
1302
+ * not finish.
1303
+ *
1304
+ * 🔑 The deleted list is a RECORD, not a progress counter. Version deletion is
1305
+ * irreversible, so a failure part-way through leaves a workspace nobody can
1306
+ * reconstruct — and throwing here would end on `handleCommandError`'s exit 2
1307
+ * ("the run could not happen") and DISCARD the document. It happened, and it
1308
+ * destroyed things the operator now has no other list of. So the lists travel
1309
+ * with the failure and the run ends 1: it happened, and its outcome is wrong.
1310
+ *
1311
+ * `failedVersions` is the other half, and the half a re-run needs: what is still
1312
+ * there. Without it the operator knows what they lost and not what they still
1313
+ * have to deal with.
1314
+ */
1315
+ export function reportHalfDeleted(report) {
1316
+ const { skillId, deletedVersions, failedVersions } = report;
1317
+ return orgCommandFailure({
1318
+ id: skillId,
1319
+ deleted: false,
1320
+ deletedVersions,
1321
+ failedVersions,
1322
+ error: report.error,
1323
+ note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted and cannot be `
1324
+ + `restored; ${String(failedVersions.length)} could not be deleted and are still there. `
1325
+ + 'The skill itself still exists — the API refuses a skill that still has versions. '
1326
+ + 'Re-run `--all` once the cause is cleared: it will attempt only what is left.',
1327
+ });
1328
+ }
1175
1329
  // ── Commands ───────────────────────────────────────────────────────────
1176
1330
  export function createOrgSkillsCommand() {
1177
1331
  const command = new Command('skills');
@@ -1279,9 +1433,16 @@ Description:
1279
1433
  the non-portable reference, non-portable command, and unqualified MCP tool-name
1280
1434
  checks — the ones that catch a skill referencing a path outside its own tree,
1281
1435
  which cannot resolve once the API publishes it alone. These WARN and never
1282
- block, and \`validation.allow\` / \`validation.severity\` from the governing
1283
- config are honoured, so a waiver that makes \`vat skills build\` green makes
1284
- this quiet too. Run \`vat audit <dir>\` for the full report.
1436
+ block. Run \`vat audit <dir>\` for the full report.
1437
+
1438
+ A ZIP faces the same three checks: its markdown members are read out of the
1439
+ archive and run through them, so a hand-built bundle is not the quiet lane.
1440
+ The one difference is the config. On a DIRECTORY, \`validation.allow\` /
1441
+ \`validation.severity\` from the governing vibe-agent-toolkit.config.yaml are
1442
+ honoured, so a waiver that makes \`vat skills build\` green makes this quiet
1443
+ too. On a ZIP there is no directory to resolve that config from — the same
1444
+ reason a config-declared eval-suite location is invisible here — so the checks
1445
+ run UNWAIVED and a warning you have already waived elsewhere will still print.
1285
1446
 
1286
1447
  There are TWO size gates and a ZIP faces both. The REQUEST gate weighs the
1287
1448
  multipart body — file bytes plus about 156 bytes of framing per file — against
@@ -1325,14 +1486,11 @@ Examples:
1325
1486
  // travels with the failure, and the run ends 1: it happened, and its
1326
1487
  // outcome is wrong.
1327
1488
  const deletedVersions = [];
1328
- const halfDeleted = (error) => orgCommandFailure({
1329
- id: skillId,
1330
- deleted: false,
1489
+ const halfDeleted = (error, failedVersions) => reportHalfDeleted({
1490
+ skillId,
1331
1491
  deletedVersions,
1492
+ failedVersions,
1332
1493
  error: error instanceof Error ? error.message : String(error),
1333
- note: `${String(deletedVersions.length)} version(s) of ${skillId} were deleted before this `
1334
- + 'failed and cannot be restored. The skill itself still exists. Re-run '
1335
- + '`--all` once the cause is cleared; the versions listed here are already gone.',
1336
1494
  });
1337
1495
  if (options.all) {
1338
1496
  const versions = await autopaginateSkills(client, skillVersionsPath(skillId));
@@ -1340,21 +1498,25 @@ Examples:
1340
1498
  // "Found …", not "Deleting …": nothing has been deleted at this point
1341
1499
  // and the very next call can be refused. Cf. `installFromLocal`.
1342
1500
  logger.info(`Found ${String(versionData.length)} version(s) of ${skillId} to delete first`);
1343
- for (const ver of versionData) {
1344
- try {
1345
- await client.deleteSkillVersion(skillId, ver.version);
1501
+ // ATTEMPTS every version, whatever any one of them answers. See
1502
+ // `deleteEveryVersion`: returning on the first refusal left the rest
1503
+ // unexamined, and the skill undeletable with no record of what remained.
1504
+ const sweep = await deleteEveryVersion(client, skillId, versionData.map(v => v.version), logger);
1505
+ deletedVersions.push(...sweep.deleted);
1506
+ if (sweep.failures.length > 0) {
1507
+ const detail = describeVersionSweepFailures(sweep.failures);
1508
+ // Nothing was destroyed, so there is no record worth publishing and
1509
+ // "could not happen" (exit 2, via the throw) is the honest ending —
1510
+ // the same rule as before, now decided on the WHOLE sweep rather than
1511
+ // on its first refusal.
1512
+ if (deletedVersions.length === 0) {
1513
+ throw new Error(`No version of ${skillId} could be deleted, so the skill was left alone. `
1514
+ + `${String(sweep.failures.length)} attempt(s) failed — ${detail}`);
1346
1515
  }
1347
- catch (error) {
1348
- // Only after at least one version is gone is there a report worth
1349
- // publishing. Before that nothing happened, and "could not happen"
1350
- // (exit 2, via the throw) is the honest ending.
1351
- if (deletedVersions.length === 0)
1352
- throw error;
1353
- logger.info(` ⚠ version ${ver.version} was not deleted`);
1354
- return halfDeleted(error);
1355
- }
1356
- deletedVersions.push(ver.version);
1357
- logger.info(` Deleted version ${ver.version}`);
1516
+ // The skill delete is not attempted: the API refuses a skill that still
1517
+ // has versions, so it would spend a round trip to be told what is
1518
+ // already known here.
1519
+ return halfDeleted(new Error(detail), sweep.failures.map(failure => failure.version));
1358
1520
  }
1359
1521
  }
1360
1522
  logger.info(`Deleting skill: ${skillId}`);
@@ -1369,7 +1531,9 @@ Examples:
1369
1531
  catch (error) {
1370
1532
  if (deletedVersions.length === 0)
1371
1533
  throw error;
1372
- return halfDeleted(error);
1534
+ // The sweep completed — every version is gone — and the SKILL delete is
1535
+ // what failed, so nothing is left in `failedVersions`.
1536
+ return halfDeleted(error, []);
1373
1537
  }
1374
1538
  const deleted = reportDelete(raw, skillId, SKILL_DELETED_TYPES);
1375
1539
  return deletedVersions.length === 0
@@ -1389,16 +1553,24 @@ Description:
1389
1553
  delete every version and then the skill in one command; without it, delete the
1390
1554
  versions yourself with \`vat claude org skills versions delete\` first.
1391
1555
 
1392
- --all deletes irreversibly and in a loop. If it fails part-way through, the
1393
- versions it already destroyed are listed under deletedVersions in the output
1394
- and the run exits 1 — the run happened, and its outcome is wrong. It exits 2
1395
- only when nothing was deleted at all.
1556
+ --all deletes irreversibly and in a loop, and it ATTEMPTS EVERY VERSION even
1557
+ when one refuses — one refusal is a fact about one version, not about the ones
1558
+ after it. When the sweep ends with anything left, the versions it destroyed are
1559
+ listed under deletedVersions, the ones still there under failedVersions, and
1560
+ the run exits 1 — the run happened, and its outcome is wrong. The skill itself
1561
+ is then left alone, because the API refuses a skill that still has versions.
1562
+ It exits 2 only when nothing was deleted at all.
1563
+
1564
+ A version delete whose response is lost is replayed, and the replay is answered
1565
+ 404 because the first attempt already removed it. That 404 is read as the
1566
+ delete it is, not as a failure — the version appears under deletedVersions.
1396
1567
 
1397
1568
  Exit Codes:
1398
1569
  0 - The skill was deleted
1399
1570
  1 - The run completed and the skill was NOT deleted: the API named a different
1400
- outcome, or --all destroyed some versions and then failed
1401
- 2 - The run could not happen: no API key, or the first request was refused
1571
+ outcome, or --all destroyed some versions and could not destroy the rest
1572
+ 2 - The run could not happen: no API key, the first request was refused, or
1573
+ --all deleted no version at all
1402
1574
 
1403
1575
  Example:
1404
1576
  $ vat claude org skills delete skill_abc123 --all