@vibe-agent-toolkit/cli 0.1.41-rc.6 → 0.1.41-rc.8

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 (199) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/vat +25 -2
  3. package/dist/bin/vat.js +25 -2
  4. package/dist/bin/vat.js.map +1 -1
  5. package/dist/bin.js +12 -1
  6. package/dist/bin.js.map +1 -1
  7. package/dist/commands/agent/list.d.ts +11 -0
  8. package/dist/commands/agent/list.d.ts.map +1 -1
  9. package/dist/commands/agent/list.js +30 -11
  10. package/dist/commands/agent/list.js.map +1 -1
  11. package/dist/commands/audit/hierarchical-output.d.ts +6 -2
  12. package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
  13. package/dist/commands/audit/hierarchical-output.js +93 -50
  14. package/dist/commands/audit/hierarchical-output.js.map +1 -1
  15. package/dist/commands/audit-settings.d.ts +35 -0
  16. package/dist/commands/audit-settings.d.ts.map +1 -1
  17. package/dist/commands/audit-settings.js +121 -51
  18. package/dist/commands/audit-settings.js.map +1 -1
  19. package/dist/commands/audit.d.ts +97 -2
  20. package/dist/commands/audit.d.ts.map +1 -1
  21. package/dist/commands/audit.js +505 -231
  22. package/dist/commands/audit.js.map +1 -1
  23. package/dist/commands/build.d.ts +14 -0
  24. package/dist/commands/build.d.ts.map +1 -1
  25. package/dist/commands/build.js +126 -32
  26. package/dist/commands/build.js.map +1 -1
  27. package/dist/commands/claude/marketplace/license-utils.d.ts +39 -2
  28. package/dist/commands/claude/marketplace/license-utils.d.ts.map +1 -1
  29. package/dist/commands/claude/marketplace/license-utils.js +114 -68
  30. package/dist/commands/claude/marketplace/license-utils.js.map +1 -1
  31. package/dist/commands/claude/marketplace/publish.js +5 -4
  32. package/dist/commands/claude/marketplace/publish.js.map +1 -1
  33. package/dist/commands/claude/marketplace/validate.d.ts +97 -0
  34. package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
  35. package/dist/commands/claude/marketplace/validate.js +157 -49
  36. package/dist/commands/claude/marketplace/validate.js.map +1 -1
  37. package/dist/commands/claude/org/skills.d.ts +11 -3
  38. package/dist/commands/claude/org/skills.d.ts.map +1 -1
  39. package/dist/commands/claude/org/skills.js +70 -20
  40. package/dist/commands/claude/org/skills.js.map +1 -1
  41. package/dist/commands/claude/org/stubs.d.ts +9 -1
  42. package/dist/commands/claude/org/stubs.d.ts.map +1 -1
  43. package/dist/commands/claude/org/stubs.js +11 -3
  44. package/dist/commands/claude/org/stubs.js.map +1 -1
  45. package/dist/commands/claude/plugin/build.d.ts +116 -0
  46. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  47. package/dist/commands/claude/plugin/build.js +173 -40
  48. package/dist/commands/claude/plugin/build.js.map +1 -1
  49. package/dist/commands/claude/plugin/marketplace-json.d.ts +36 -0
  50. package/dist/commands/claude/plugin/marketplace-json.d.ts.map +1 -0
  51. package/dist/commands/claude/plugin/marketplace-json.js +34 -0
  52. package/dist/commands/claude/plugin/marketplace-json.js.map +1 -0
  53. package/dist/commands/claude/plugin/plugin-json-merge.d.ts +30 -1
  54. package/dist/commands/claude/plugin/plugin-json-merge.d.ts.map +1 -1
  55. package/dist/commands/claude/plugin/plugin-json-merge.js +107 -14
  56. package/dist/commands/claude/plugin/plugin-json-merge.js.map +1 -1
  57. package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
  58. package/dist/commands/claude/plugin/tree-copy.js +0 -1
  59. package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
  60. package/dist/commands/corpus/report.d.ts +22 -4
  61. package/dist/commands/corpus/report.d.ts.map +1 -1
  62. package/dist/commands/corpus/report.js +1 -0
  63. package/dist/commands/corpus/report.js.map +1 -1
  64. package/dist/commands/corpus/runner.d.ts +16 -1
  65. package/dist/commands/corpus/runner.d.ts.map +1 -1
  66. package/dist/commands/corpus/runner.js +55 -48
  67. package/dist/commands/corpus/runner.js.map +1 -1
  68. package/dist/commands/doctor.d.ts +57 -8
  69. package/dist/commands/doctor.d.ts.map +1 -1
  70. package/dist/commands/doctor.js +142 -67
  71. package/dist/commands/doctor.js.map +1 -1
  72. package/dist/commands/inventory.d.ts +2 -0
  73. package/dist/commands/inventory.d.ts.map +1 -1
  74. package/dist/commands/inventory.js +45 -4
  75. package/dist/commands/inventory.js.map +1 -1
  76. package/dist/commands/phase-utils.d.ts +240 -11
  77. package/dist/commands/phase-utils.d.ts.map +1 -1
  78. package/dist/commands/phase-utils.js +352 -15
  79. package/dist/commands/phase-utils.js.map +1 -1
  80. package/dist/commands/rag/query-command.d.ts +40 -0
  81. package/dist/commands/rag/query-command.d.ts.map +1 -1
  82. package/dist/commands/rag/query-command.js +47 -20
  83. package/dist/commands/rag/query-command.js.map +1 -1
  84. package/dist/commands/resources/index.d.ts.map +1 -1
  85. package/dist/commands/resources/index.js +38 -13
  86. package/dist/commands/resources/index.js.map +1 -1
  87. package/dist/commands/resources/scan.d.ts +37 -0
  88. package/dist/commands/resources/scan.d.ts.map +1 -1
  89. package/dist/commands/resources/scan.js +47 -32
  90. package/dist/commands/resources/scan.js.map +1 -1
  91. package/dist/commands/resources/validate.d.ts +136 -1
  92. package/dist/commands/resources/validate.d.ts.map +1 -1
  93. package/dist/commands/resources/validate.js +121 -68
  94. package/dist/commands/resources/validate.js.map +1 -1
  95. package/dist/commands/skill/review.d.ts.map +1 -1
  96. package/dist/commands/skill/review.js +40 -23
  97. package/dist/commands/skill/review.js.map +1 -1
  98. package/dist/commands/skill/test/run.d.ts +1 -1
  99. package/dist/commands/skill/test/run.d.ts.map +1 -1
  100. package/dist/commands/skill/test/run.js +8 -6
  101. package/dist/commands/skill/test/run.js.map +1 -1
  102. package/dist/commands/skills/build.d.ts +140 -0
  103. package/dist/commands/skills/build.d.ts.map +1 -1
  104. package/dist/commands/skills/build.js +348 -94
  105. package/dist/commands/skills/build.js.map +1 -1
  106. package/dist/commands/skills/command-helpers.d.ts +6 -10
  107. package/dist/commands/skills/command-helpers.d.ts.map +1 -1
  108. package/dist/commands/skills/command-helpers.js +6 -22
  109. package/dist/commands/skills/command-helpers.js.map +1 -1
  110. package/dist/commands/skills/list.d.ts +18 -0
  111. package/dist/commands/skills/list.d.ts.map +1 -1
  112. package/dist/commands/skills/list.js +41 -15
  113. package/dist/commands/skills/list.js.map +1 -1
  114. package/dist/commands/skills/package.d.ts +17 -0
  115. package/dist/commands/skills/package.d.ts.map +1 -1
  116. package/dist/commands/skills/package.js +72 -43
  117. package/dist/commands/skills/package.js.map +1 -1
  118. package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
  119. package/dist/commands/skills/skill-discovery.js +9 -1
  120. package/dist/commands/skills/skill-discovery.js.map +1 -1
  121. package/dist/commands/skills/validate-command.d.ts.map +1 -1
  122. package/dist/commands/skills/validate-command.js +22 -6
  123. package/dist/commands/skills/validate-command.js.map +1 -1
  124. package/dist/commands/skills/validate.d.ts +79 -0
  125. package/dist/commands/skills/validate.d.ts.map +1 -1
  126. package/dist/commands/skills/validate.js +268 -79
  127. package/dist/commands/skills/validate.js.map +1 -1
  128. package/dist/commands/validate.d.ts +18 -0
  129. package/dist/commands/validate.d.ts.map +1 -1
  130. package/dist/commands/validate.js +79 -66
  131. package/dist/commands/validate.js.map +1 -1
  132. package/dist/commands/verify.d.ts +38 -1
  133. package/dist/commands/verify.d.ts.map +1 -1
  134. package/dist/commands/verify.js +247 -84
  135. package/dist/commands/verify.js.map +1 -1
  136. package/dist/index.d.ts +1 -1
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +7 -1
  139. package/dist/index.js.map +1 -1
  140. package/dist/skill-resolution/index.d.ts +1 -1
  141. package/dist/skill-resolution/index.d.ts.map +1 -1
  142. package/dist/skill-resolution/index.js +1 -1
  143. package/dist/skill-resolution/index.js.map +1 -1
  144. package/dist/skill-resolution/packaging-config.d.ts +15 -2
  145. package/dist/skill-resolution/packaging-config.d.ts.map +1 -1
  146. package/dist/skill-resolution/packaging-config.js +39 -2
  147. package/dist/skill-resolution/packaging-config.js.map +1 -1
  148. package/dist/utils/command-error.d.ts +34 -1
  149. package/dist/utils/command-error.d.ts.map +1 -1
  150. package/dist/utils/command-error.js +32 -1
  151. package/dist/utils/command-error.js.map +1 -1
  152. package/dist/utils/config-loader.d.ts.map +1 -1
  153. package/dist/utils/config-loader.js +0 -2
  154. package/dist/utils/config-loader.js.map +1 -1
  155. package/dist/utils/help-loader.d.ts +6 -2
  156. package/dist/utils/help-loader.d.ts.map +1 -1
  157. package/dist/utils/help-loader.js +9 -16
  158. package/dist/utils/help-loader.js.map +1 -1
  159. package/dist/utils/issue-anchor.d.ts +26 -0
  160. package/dist/utils/issue-anchor.d.ts.map +1 -0
  161. package/dist/utils/issue-anchor.js +39 -0
  162. package/dist/utils/issue-anchor.js.map +1 -0
  163. package/dist/utils/issue-rendering.d.ts +149 -0
  164. package/dist/utils/issue-rendering.d.ts.map +1 -0
  165. package/dist/utils/issue-rendering.js +229 -0
  166. package/dist/utils/issue-rendering.js.map +1 -0
  167. package/dist/utils/output.d.ts +80 -9
  168. package/dist/utils/output.d.ts.map +1 -1
  169. package/dist/utils/output.js +138 -23
  170. package/dist/utils/output.js.map +1 -1
  171. package/dist/utils/project-root-policy.d.ts +2 -2
  172. package/dist/utils/project-root-policy.js +2 -2
  173. package/dist/utils/relativize-paths.d.ts +45 -0
  174. package/dist/utils/relativize-paths.d.ts.map +1 -0
  175. package/dist/utils/relativize-paths.js +67 -0
  176. package/dist/utils/relativize-paths.js.map +1 -0
  177. package/dist/utils/resource-loader.d.ts +21 -2
  178. package/dist/utils/resource-loader.d.ts.map +1 -1
  179. package/dist/utils/resource-loader.js +85 -11
  180. package/dist/utils/resource-loader.js.map +1 -1
  181. package/dist/utils/skill-packaging-config.d.ts +22 -1
  182. package/dist/utils/skill-packaging-config.d.ts.map +1 -1
  183. package/dist/utils/skill-packaging-config.js +26 -0
  184. package/dist/utils/skill-packaging-config.js.map +1 -1
  185. package/dist/utils/validate-help-files.d.ts +3 -2
  186. package/dist/utils/validate-help-files.d.ts.map +1 -1
  187. package/dist/utils/validate-help-files.js +48 -5
  188. package/dist/utils/validate-help-files.js.map +1 -1
  189. package/dist/utils/verdict-helpers.d.ts +14 -5
  190. package/dist/utils/verdict-helpers.d.ts.map +1 -1
  191. package/dist/utils/verdict-helpers.js +19 -16
  192. package/dist/utils/verdict-helpers.js.map +1 -1
  193. package/docs/audit.md +40 -14
  194. package/docs/doctor.md +46 -10
  195. package/docs/index.md +1 -1
  196. package/docs/rag.md +9 -4
  197. package/docs/resources.md +54 -22
  198. package/docs/skills.md +11 -7
  199. package/package.json +12 -12
@@ -6,16 +6,27 @@
6
6
  * (commands, hooks, agents, .mcp.json, skills/, .claude-plugin/plugin.json) and
7
7
  * imports pool skills (from dist/skills/) via the `skills:` selector.
8
8
  */
9
+ import { type SeverityCounts } from '@vibe-agent-toolkit/agent-schema';
10
+ import { type DeclaredEvalSuite, type PackageSkillResult } from '@vibe-agent-toolkit/agent-skills';
11
+ import type { ResourceRegistry, SkillsConfig } from '@vibe-agent-toolkit/resources';
9
12
  import { Command } from 'commander';
10
13
  import { createLogger } from '../../../utils/logger.js';
11
14
  export interface PluginBuildCommandOptions {
12
15
  marketplace?: string;
13
16
  debug?: boolean;
17
+ verbose?: boolean;
14
18
  }
15
19
  interface PluginBuildResult {
16
20
  pluginName: string;
17
21
  pluginDir: string;
18
22
  pluginVersion: string | undefined;
23
+ /**
24
+ * The plugin's merged `author` (config-owned name/email plus the subfields
25
+ * config cannot express, passed through from the author's plugin.json). Carried
26
+ * up so marketplace.json republishes THIS object rather than rebuilding one
27
+ * from the config `owner` and silently dropping the passthrough subfields.
28
+ */
29
+ pluginAuthor: Record<string, unknown>;
19
30
  skillsCopied: string[];
20
31
  commandsCopied: number;
21
32
  hooksCopied: number;
@@ -24,6 +35,15 @@ interface PluginBuildResult {
24
35
  treeFilesCopied: number;
25
36
  explicitFilesCopied: number;
26
37
  localSkillsPackaged: number;
38
+ /**
39
+ * Per-severity post-build findings across this plugin's plugin-local skills.
40
+ *
41
+ * Published rather than folded into the plugin's success/failure: the build
42
+ * gate is two-valued (a warning does not fail it), so a bare `status` cannot
43
+ * say whether a "built" plugin shipped warnings or info findings — and the
44
+ * reading a consumer takes from silence is the reassuring one.
45
+ */
46
+ localSkillIssueCounts: SeverityCounts;
27
47
  }
28
48
  export interface MarketplaceBuildResult {
29
49
  name: string;
@@ -45,10 +65,106 @@ export declare function createPluginBuildCommand(): Command;
45
65
  * vibe-agent-toolkit.config.yaml), so callers that already know the root build
46
66
  * against it rather than re-discovering from cwd. `options.marketplace` restricts
47
67
  * the build to a single marketplace by name.
68
+ *
69
+ * `options.verbose` affects the stderr findings report ONLY (see
70
+ * `summarizePackagedSkillIssues`); it changes nothing this function returns, so a
71
+ * programmatic caller — `vat skill test`, which builds a marketplace purely to
72
+ * stage a skill — can leave it off and still get the same result objects.
48
73
  */
49
74
  export declare function runClaudePluginBuild(configDir: string, options?: {
50
75
  marketplace?: string;
51
76
  logger?: ReturnType<typeof createLogger>;
77
+ verbose?: boolean;
52
78
  }): Promise<MarketplaceBuildResult[]>;
79
+ /** One plugin-local skill, discovered once and carried through every later phase. */
80
+ interface PluginLocalSkill {
81
+ /** Forward-slash dir path relative to the plugin's `skills/` dir (`a`, `group/b`). */
82
+ skillDirPath: string;
83
+ /** Absolute path to its `SKILL.md`. */
84
+ skillPath: string;
85
+ /** Its DECLARED name (frontmatter → H1 → filename), the key per-skill config uses. */
86
+ skillName: string;
87
+ }
88
+ /**
89
+ * PACKAGE each plugin-local skill (a skill living in the plugin's own `skills/`
90
+ * source tree) with the SAME packager that produces pool skills.
91
+ *
92
+ * This is the "one production path" rule. A plugin-local skill used to be
93
+ * tree-copied VERBATIM — every byte in its source directory shipped, links were
94
+ * never rewritten, and `files:` had to be re-applied separately because the
95
+ * packager never ran. That produced a materially different artifact from the
96
+ * pool path for the same kind of thing, and the difference was invisible: it
97
+ * shipped eval suites (answer keys included), scratch files, and un-rewritten
98
+ * links. The collision referee already conceded the point by preferring the
99
+ * pool copy whenever both existed.
100
+ *
101
+ * Now both paths run `packageSkill`, so "what ships in a skill" has exactly one
102
+ * answer: link-reachable resources plus declared `files:`, links rewritten,
103
+ * declared test input excluded, post-build checks applied.
104
+ *
105
+ * `input.skills` is the already-refereed set: pool-sourced collisions have been
106
+ * filtered out by {@link resolveCollidingSkills} and are copied in by Phase 3
107
+ * instead. Returns each packaged skill's result for error reporting.
108
+ *
109
+ * The returned list is also the ONLY definition of "which dirs under `skills/` did
110
+ * the packager produce": the tree-copy exclusion list is derived from it (see
111
+ * Phase 2b in {@link buildPlugin}), so a directory absent from it is a directory
112
+ * the tree-copy still ships.
113
+ */
114
+ export declare function packagePluginLocalSkills(input: {
115
+ skills: readonly PluginLocalSkill[];
116
+ pluginDir: string;
117
+ skillsConfig: SkillsConfig | undefined;
118
+ /**
119
+ * THE project registry for this build, built once by {@link runClaudePluginBuild}.
120
+ *
121
+ * Not optional, and not defaulted: `packageSkill` silently falls back to
122
+ * crawling and parsing every markdown file in the project when it gets no
123
+ * registry, so an omission here costs one whole-project scan PER SKILL rather
124
+ * than failing. That is exactly what this lane used to do.
125
+ */
126
+ registry: ResourceRegistry;
127
+ /**
128
+ * THE project's declared eval suites, assembled once by {@link runClaudePluginBuild}.
129
+ *
130
+ * Not optional, and not defaulted, for the same reason as `registry` above: an
131
+ * omission would not fail, it would silently package one skill's bundle carrying
132
+ * ANOTHER skill's eval answer key — the failure mode a default value hid the first
133
+ * time this rule shipped.
134
+ */
135
+ projectSkills: readonly DeclaredEvalSuite[];
136
+ logger: ReturnType<typeof createLogger>;
137
+ }): Promise<Array<{
138
+ skillDirPath: string;
139
+ result: PackageSkillResult;
140
+ }>>;
141
+ /**
142
+ * Summarize post-build issues for the plugin-local skills: the lines to print,
143
+ * the dirs that emitted errors, and the per-severity distribution.
144
+ *
145
+ * Mirrors `vat skills build`: a skill whose packaged output fails validation
146
+ * fails the build, so the two lanes hold the same bar, and they now render
147
+ * findings through the same helper — this lane used to label every non-error
148
+ * severity `[WARNING]`, so `info` findings were reported as warnings, and it
149
+ * read only `postBuildIssues`, so a skill failing purely on the built-output
150
+ * validation aborted the plugin build with no issue text at all.
151
+ *
152
+ * `verbose` governs the RENDERED lines and nothing else: `withErrors` (what the
153
+ * caller fails the plugin on) and `issueCounts` (what stdout publishes) are
154
+ * computed from the whole set at every verbosity, so quieting the report cannot
155
+ * quiet the gate. Per the shared policy in `issuesToRenderAtVerbosity`, errors
156
+ * always get a full block; warnings and info collapse into the per-skill heading
157
+ * above them, which still names the complete severity breakdown.
158
+ *
159
+ * Pure so the whole rendered set is assertable.
160
+ */
161
+ export declare function summarizePackagedSkillIssues(packaged: Array<{
162
+ skillDirPath: string;
163
+ result: PackageSkillResult;
164
+ }>, verbose: boolean): {
165
+ lines: string[];
166
+ withErrors: string[];
167
+ issueCounts: SeverityCounts;
168
+ };
53
169
  export {};
54
170
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/build.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAexD,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAgDlD;AAkBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;CAAO,GAC/E,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAyEnC"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/build.ts"],"names":[],"mappings":"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"}
@@ -9,16 +9,20 @@
9
9
  import { cpSync, existsSync, readFileSync } from 'node:fs';
10
10
  import { mkdir, readdir, rm, writeFile } from 'node:fs/promises';
11
11
  import { basename } from 'node:path';
12
- import { getPluginOutputDir, getPluginSourceDir, listPluginSourceSkillDirs, listUntrackedPluginSkillDirs, packageSkill, packagingConfigToPackageOptions, skillNameToFsPath } from '@vibe-agent-toolkit/agent-skills';
12
+ import { countBySeverity } from '@vibe-agent-toolkit/agent-schema';
13
+ import { createProjectRegistry, getPluginOutputDir, getPluginSourceDir, listPluginSourceSkillDirs, listUntrackedPluginSkillDirs, packageSkill, packagingConfigToPackageOptions, skillNameToFsPath } from '@vibe-agent-toolkit/agent-skills';
13
14
  import { safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
14
15
  import { Command } from 'commander';
15
16
  import { readSkillName } from '../../../commands/skills/skill-discovery.js';
16
17
  import { handleCommandError } from '../../../utils/command-error.js';
17
18
  import { loadConfig } from '../../../utils/config-loader.js';
19
+ import { collectPostBuildIssues, formatIssueLines, formatIssueSetHeading, issuesToRenderAtVerbosity, sumSeverityCounts, } from '../../../utils/issue-rendering.js';
18
20
  import { createLogger } from '../../../utils/logger.js';
19
21
  import { writeYamlOutput } from '../../../utils/output.js';
20
- import { mergeSkillPackagingConfig } from '../../../utils/skill-packaging-config.js';
22
+ import { collectDeclaredEvalSuites, mergeSkillPackagingConfig } from '../../../utils/skill-packaging-config.js';
23
+ import { discoverSkillsFromConfig } from '../../skills/skill-discovery.js';
21
24
  import { loadClaudeProjectConfig } from '../claude-config.js';
25
+ import { buildMarketplaceJson } from './marketplace-json.js';
22
26
  import { resolvePluginChangelogPath } from './plugin-changelog.js';
23
27
  import { applyPluginFiles } from './plugin-files.js';
24
28
  import { mergePluginJson, resolveVersion } from './plugin-json-merge.js';
@@ -30,6 +34,7 @@ export function createPluginBuildCommand() {
30
34
  command
31
35
  .description('Generate Claude plugin artifacts from plugin directories and pre-built skills')
32
36
  .option('--marketplace <name>', 'Build specific marketplace only')
37
+ .option('-v, --verbose', 'Show every individual finding, not just the errors')
33
38
  .option('--debug', 'Enable debug logging')
34
39
  .action(pluginBuildCommand)
35
40
  .addHelpText('after', `
@@ -59,6 +64,12 @@ Output:
59
64
  YAML summary -> stdout
60
65
  Build progress -> stderr
61
66
 
67
+ On stderr, each packaged skill's findings heading names the whole set and
68
+ its severity breakdown, and errors are always printed in full beneath it.
69
+ Warnings and info findings stay collapsed into that heading unless
70
+ --verbose. The stdout YAML is NOT affected by --verbose: its issueCounts
71
+ cover every finding at every verbosity.
72
+
62
73
  Exit Codes:
63
74
  0 - Build successful
64
75
  1 - Build error (empty plugin, invalid config)
@@ -95,9 +106,15 @@ async function discoverBuiltSkills(configDir) {
95
106
  * vibe-agent-toolkit.config.yaml), so callers that already know the root build
96
107
  * against it rather than re-discovering from cwd. `options.marketplace` restricts
97
108
  * the build to a single marketplace by name.
109
+ *
110
+ * `options.verbose` affects the stderr findings report ONLY (see
111
+ * `summarizePackagedSkillIssues`); it changes nothing this function returns, so a
112
+ * programmatic caller — `vat skill test`, which builds a marketplace purely to
113
+ * stage a skill — can leave it off and still get the same result objects.
98
114
  */
99
115
  export async function runClaudePluginBuild(configDir, options = {}) {
100
116
  const logger = options.logger ?? createLogger({});
117
+ const verbose = options.verbose === true;
101
118
  const projectConfig = loadConfig(configDir);
102
119
  const marketplaces = projectConfig?.claude?.marketplaces;
103
120
  if (!marketplaces || Object.keys(marketplaces).length === 0) {
@@ -128,6 +145,22 @@ export async function runClaudePluginBuild(configDir, options = {}) {
128
145
  logger.info(`Building Claude plugin artifacts`);
129
146
  logger.info(` Config: ${safePath.join(configDir, 'vibe-agent-toolkit.config.yaml')}`);
130
147
  logger.info(` Skills available: ${availableSkills.length}`);
148
+ // THE registry for this build: one crawl+parse of the project's markdown,
149
+ // shared by every plugin-local skill in every marketplace. `packageSkill`
150
+ // builds this itself when it is not given one, so omitting it does not fail —
151
+ // it just re-reads the whole project once per skill, which is how a 46-skill
152
+ // build came to take longer than a 30-minute CI budget.
153
+ const sharedRegistry = await createProjectRegistry(configDir);
154
+ logger.debug(`Project registry: ${sharedRegistry.getAllResources().length} markdown resources (built once)`);
155
+ // THE project's declared eval suites for this build, assembled ONCE and threaded
156
+ // to every plugin-local skill. Test input never ships, and the rule is
157
+ // project-wide: a file ANY skill declares as its eval suite is an answer key, so
158
+ // a plugin-local skill's bundle must exclude the OTHER skills' suites too — not
159
+ // just its own. Discovery is not free, hence once per run rather than per skill.
160
+ const projectSkills = skillsConfig === undefined
161
+ ? []
162
+ : collectDeclaredEvalSuites(skillsConfig, await discoverSkillsFromConfig(skillsConfig, configDir));
163
+ logger.debug(`Project declared eval suites: ${projectSkills.length}`);
131
164
  const results = [];
132
165
  const allPluginNames = [];
133
166
  for (const mp of Object.values(marketplaces)) {
@@ -142,7 +175,18 @@ export async function runClaudePluginBuild(configDir, options = {}) {
142
175
  }
143
176
  const mpConfig = marketplaces[name];
144
177
  logger.info(`\n Building marketplace: ${name}`);
145
- const result = await buildMarketplace(name, mpConfig, availableSkills, configDir, skillsConfig, rootVersion, logger);
178
+ const result = await buildMarketplace({
179
+ name,
180
+ config: mpConfig,
181
+ availableSkills,
182
+ configDir,
183
+ skillsConfig,
184
+ rootVersion,
185
+ registry: sharedRegistry,
186
+ projectSkills,
187
+ logger,
188
+ verbose,
189
+ });
146
190
  results.push(result);
147
191
  if (result.status === 'error') {
148
192
  throw new Error(`Claude plugin build failed for marketplace '${name}': ${result.reason ?? 'unknown error'}`);
@@ -166,12 +210,17 @@ async function pluginBuildCommand(options) {
166
210
  const results = await runClaudePluginBuild(configDir, {
167
211
  ...(options.marketplace ? { marketplace: options.marketplace } : {}),
168
212
  logger,
213
+ verbose: options.verbose === true,
169
214
  });
170
215
  const duration = Date.now() - startTime;
171
216
  const totalPlugins = results.flatMap((r) => r.plugins).length;
172
217
  const totalSkills = results.flatMap((r) => r.plugins).flatMap((p) => p.skillsCopied).length;
218
+ const allPlugins = results.flatMap((r) => r.plugins);
173
219
  writeYamlOutput({
174
220
  status: 'success',
221
+ // The build gate is two-valued and a warning does not fail it, so the
222
+ // distribution has to travel next to the status rather than inside it.
223
+ issueCounts: sumSeverityCounts(allPlugins.map((p) => p.localSkillIssueCounts)),
175
224
  marketplacesBuilt: results.filter((r) => r.status === 'built').length,
176
225
  pluginsBuilt: totalPlugins,
177
226
  skillsPackaged: totalSkills,
@@ -190,6 +239,7 @@ async function pluginBuildCommand(options) {
190
239
  treeFilesCopied: p.treeFilesCopied,
191
240
  explicitFilesCopied: p.explicitFilesCopied,
192
241
  localSkillsPackaged: p.localSkillsPackaged,
242
+ issueCounts: p.localSkillIssueCounts,
193
243
  })),
194
244
  })),
195
245
  duration: `${duration}ms`,
@@ -224,7 +274,8 @@ async function copyDistributionFiles(marketplaceDir, configDir, config, logger)
224
274
  }
225
275
  }
226
276
  }
227
- async function buildMarketplace(name, config, availableSkills, configDir, skillsConfig, rootVersion, logger) {
277
+ async function buildMarketplace(input) {
278
+ const { name, config, availableSkills, configDir, skillsConfig, rootVersion, registry, projectSkills, logger, verbose } = input;
228
279
  const plugins = [];
229
280
  // Clean stale marketplace directory before rebuilding — removes orphaned plugins
230
281
  const marketplaceBaseDir = safePath.join(configDir, 'dist', '.claude', 'plugins', 'marketplaces', name);
@@ -243,7 +294,10 @@ async function buildMarketplace(name, config, availableSkills, configDir, skills
243
294
  skillsConfig,
244
295
  owner: config.owner,
245
296
  rootVersion,
297
+ registry,
298
+ projectSkills,
246
299
  logger,
300
+ verbose,
247
301
  });
248
302
  plugins.push(pluginResult);
249
303
  }
@@ -252,27 +306,18 @@ async function buildMarketplace(name, config, availableSkills, configDir, skills
252
306
  const claudePluginDir = safePath.join(marketplaceDir, CLAUDE_PLUGIN_DIRNAME);
253
307
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved paths
254
308
  await mkdir(claudePluginDir, { recursive: true });
255
- const marketplaceJson = {
256
- $schema: 'https://anthropic.com/claude-code/marketplace.schema.json',
309
+ // Each entry's author is the plugin's own MERGED author (see marketplace-json.ts),
310
+ // so marketplace.json and that plugin's plugin.json cannot disagree.
311
+ const marketplaceJson = buildMarketplaceJson({
257
312
  name,
258
- owner: {
259
- name: config.owner.name,
260
- ...(config.owner.email ? { email: config.owner.email } : {}),
261
- },
262
- plugins: plugins.map((p) => {
263
- const pluginDesc = config.plugins.find((pd) => pd.name === p.pluginName)?.description;
264
- return {
265
- name: p.pluginName,
266
- ...(pluginDesc ? { description: pluginDesc } : {}),
267
- source: `./plugins/${p.pluginName}`,
268
- ...(p.pluginVersion ? { version: p.pluginVersion } : {}),
269
- author: {
270
- name: config.owner.name,
271
- ...(config.owner.email ? { email: config.owner.email } : {}),
272
- },
273
- };
274
- }),
275
- };
313
+ owner: config.owner,
314
+ plugins: plugins.map((p) => ({
315
+ name: p.pluginName,
316
+ description: config.plugins.find((pd) => pd.name === p.pluginName)?.description,
317
+ version: p.pluginVersion,
318
+ author: p.pluginAuthor,
319
+ })),
320
+ });
276
321
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved paths
277
322
  await writeFile(safePath.join(claudePluginDir, 'marketplace.json'), JSON.stringify(marketplaceJson, null, 2));
278
323
  logger.info(` .claude-plugin/marketplace.json`);
@@ -355,7 +400,7 @@ async function writeMergedPluginJson(pluginDef, authorJson, pluginVersion, plugi
355
400
  const pluginJsonDir = safePath.join(pluginDir, CLAUDE_PLUGIN_DIRNAME);
356
401
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved paths
357
402
  await mkdir(pluginJsonDir, { recursive: true });
358
- const { merged, warnings } = mergePluginJson({
403
+ const { merged, author, warnings } = mergePluginJson({
359
404
  vat: {
360
405
  name: pluginDef.name,
361
406
  version: pluginVersion,
@@ -369,6 +414,7 @@ async function writeMergedPluginJson(pluginDef, authorJson, pluginVersion, plugi
369
414
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved paths
370
415
  await writeFile(safePath.join(pluginJsonDir, 'plugin.json'), JSON.stringify(merged, null, 2));
371
416
  logger.info(` .claude-plugin/plugin.json`);
417
+ return author;
372
418
  }
373
419
  /**
374
420
  * Copy pool skills (from dist/skills/) selected by the plugin's skills: selector
@@ -470,8 +516,31 @@ function lastPathSegment(dirPath) {
470
516
  * Phase 2b in {@link buildPlugin}), so a directory absent from it is a directory
471
517
  * the tree-copy still ships.
472
518
  */
473
- async function packagePluginLocalSkills(input) {
519
+ export async function packagePluginLocalSkills(input) {
474
520
  const packaged = [];
521
+ // KNOWN GAP — NO PER-SKILL CONTAINMENT. `packageSkill` reports most problems by
522
+ // RETURNING a result whose `hasErrors` is set, but it THROWS on structural packaging
523
+ // failures (filename collisions, unreadable sources). This loop awaits it bare, so one
524
+ // throw escapes the whole plugin build and discards every skill packaged before it —
525
+ // while the partial `skills/<dir>/` trees already written stay on disk, described by
526
+ // nothing.
527
+ //
528
+ // This is the SAME defect, in the same shape, that `packageSkills` had until commit
529
+ // ba140fae ("fix(skills): one unbuildable skill no longer discards the whole build").
530
+ // Copy that fix: it wraps each iteration in try/catch and returns a
531
+ // `SkillPackageOutcome` discriminated union (`built` | `failed`) carrying the error,
532
+ // deliberately NOT a synthetic `PackageSkillResult` (which would have to invent
533
+ // `outputPath`/`skill`/`files`, so consumers would report a file count for a bundle
534
+ // that is not on disk).
535
+ //
536
+ // Why it matters concretely: a `vat build` on a 90-skill adopter (2026-07-30) hit 3
537
+ // filename collisions across three separate skills and, thanks to `packageSkills`'
538
+ // containment, still built the other 87. This lane would have thrown all 90 away.
539
+ //
540
+ // Note the containment this lane lacks is for a skill that THROWS, and a filename
541
+ // collision no longer throws — it is a returned finding. The remaining throw paths
542
+ // are an absent or unreadable `files:` source; do not use a collision as the fixture
543
+ // when adding that guard, or the test will pass without the guard existing.
475
544
  for (const { skillDirPath, skillPath, skillName } of input.skills) {
476
545
  // Per-skill config is keyed by the skill's declared NAME; the directory path and
477
546
  // its trailing segment are fallbacks for the common cases where they coincide.
@@ -483,30 +552,90 @@ async function packagePluginLocalSkills(input) {
483
552
  input.skillsConfig?.config?.[skillDirPath] ??
484
553
  input.skillsConfig?.config?.[lastPathSegment(skillDirPath)]);
485
554
  const skillOutputDir = safePath.join(input.pluginDir, 'skills', skillDirPath);
486
- const result = await packageSkill(skillPath, packagingConfigToPackageOptions(packagingConfig, { skillPath, outputPath: skillOutputDir }));
555
+ // KNOWN GAP — false ALLOW_UNUSED for plugin-local skills. If you are here, please
556
+ // consider fixing it while the hood is open.
557
+ //
558
+ // This loop omits `allowLedger`, and omitting it is a positive claim that THIS
559
+ // call is the whole run (see PackageSkillOptions.allowLedger). That claim is FALSE
560
+ // here: we are looping. `validation.allow` is declared once per package but matched
561
+ // once per skill, so an entry matched while packaging skill A is reported unused
562
+ // while packaging skill B. `vat skills build` had exactly this bug and fixed it by
563
+ // creating one ledger for the invocation, threading it through, and draining it
564
+ // once after the last skill — see `runSkillBuild` in ../../skills/build.ts, which
565
+ // is the model to copy.
566
+ //
567
+ // Why it is not fixed here: this lane has no channel for RUN-level issues in its
568
+ // YAML output (every issue it reports is attributed to a skill dir), and inventing
569
+ // a second reporting shape was worse than leaving one honest comment. Fixing this
570
+ // properly means adding that channel first.
571
+ //
572
+ // Why it measures zero today: VAT's own plugins are assembled from the shared skill
573
+ // pool by copy-in, so this loop packages nothing. A project with plugin-local
574
+ // `skills/` directories AND package-scoped `validation.allow` entries still sees the
575
+ // false warnings. This is also the last thing blocking a promotion of ALLOW_UNUSED
576
+ // from `warning` to `error`, which would turn those false positives into hard build
577
+ // failures.
578
+ //
579
+ // That promotion is now MEASURABLE rather than open-ended. On the 90-skill adopter
580
+ // (2026-07-30) this lane's ledger drains to 17 unused allow entries, against 14 in
581
+ // the `vat skills build` (`skills`) lane — so the work this comment gates is a
582
+ // bounded 17-entry reconciliation, not an unbounded one. UNVERIFIED how much of the
583
+ // 17 - 14 delta is the false-positive class described above versus genuinely dead
584
+ // entries; nobody has classified them entry by entry.
585
+ const result = await packageSkill(skillPath, {
586
+ ...packagingConfigToPackageOptions(packagingConfig, { skillPath, outputPath: skillOutputDir }, input.projectSkills),
587
+ registry: input.registry,
588
+ });
487
589
  input.logger.info(` ${skillName} -> skills/${skillDirPath} (${result.files.dependencies.length + 1} files)`);
488
590
  packaged.push({ skillDirPath, result });
489
591
  }
490
592
  return packaged;
491
593
  }
492
594
  /**
493
- * Report post-build issues for the plugin-local skills and return the names that
494
- * emitted errors. Mirrors `vat skills build`: a skill whose packaged output fails
495
- * validation fails the build, so the two lanes hold the same bar. This is new
496
- * enforcement for plugin-local skills — the verbatim tree-copy never validated
497
- * anything it shipped.
595
+ * Summarize post-build issues for the plugin-local skills: the lines to print,
596
+ * the dirs that emitted errors, and the per-severity distribution.
597
+ *
598
+ * Mirrors `vat skills build`: a skill whose packaged output fails validation
599
+ * fails the build, so the two lanes hold the same bar, and they now render
600
+ * findings through the same helper — this lane used to label every non-error
601
+ * severity `[WARNING]`, so `info` findings were reported as warnings, and it
602
+ * read only `postBuildIssues`, so a skill failing purely on the built-output
603
+ * validation aborted the plugin build with no issue text at all.
604
+ *
605
+ * `verbose` governs the RENDERED lines and nothing else: `withErrors` (what the
606
+ * caller fails the plugin on) and `issueCounts` (what stdout publishes) are
607
+ * computed from the whole set at every verbosity, so quieting the report cannot
608
+ * quiet the gate. Per the shared policy in `issuesToRenderAtVerbosity`, errors
609
+ * always get a full block; warnings and info collapse into the per-skill heading
610
+ * above them, which still names the complete severity breakdown.
611
+ *
612
+ * Pure so the whole rendered set is assertable.
498
613
  */
499
- function reportPackagedSkillIssues(packaged, logger) {
614
+ export function summarizePackagedSkillIssues(packaged, verbose) {
615
+ const lines = [];
500
616
  const withErrors = [];
617
+ const perSkillCounts = [];
501
618
  for (const { skillDirPath, result } of packaged) {
502
- for (const issue of result.postBuildIssues ?? []) {
503
- const prefix = issue.severity === 'error' ? 'ERROR' : 'WARNING';
504
- logger.info(` [${prefix}] [${String(issue.code)}] ${String(issue.message)}`);
619
+ const issues = collectPostBuildIssues(result);
620
+ perSkillCounts.push(countBySeverity(issues));
621
+ if (issues.length > 0) {
622
+ lines.push(` ${skillDirPath}: ${formatIssueSetHeading(issues, 'post-build')}`);
623
+ for (const issue of issuesToRenderAtVerbosity(issues, verbose)) {
624
+ lines.push(...formatIssueLines(issue, ' '));
625
+ }
505
626
  }
506
627
  if (result.hasErrors)
507
628
  withErrors.push(skillDirPath);
508
629
  }
509
- return withErrors;
630
+ return { lines, withErrors, issueCounts: sumSeverityCounts(perSkillCounts) };
631
+ }
632
+ /** Print the summary to stderr and return what the caller gates on. */
633
+ function reportPackagedSkillIssues(packaged, logger, verbose) {
634
+ const { lines, withErrors, issueCounts } = summarizePackagedSkillIssues(packaged, verbose);
635
+ for (const line of lines) {
636
+ logger.info(line);
637
+ }
638
+ return { withErrors, issueCounts };
510
639
  }
511
640
  /**
512
641
  * Split the plugin's own skills into those that COLLIDE with its resolved pool
@@ -554,7 +683,7 @@ function resolveCollidingSkills(skills, selectedSkillNames) {
554
683
  return { colliding, packageable, conflicts };
555
684
  }
556
685
  async function buildPlugin(input) {
557
- const { marketplaceName, pluginDef, marketplaceAvailable, configDir, skillsConfig, owner, rootVersion, logger } = input;
686
+ const { marketplaceName, pluginDef, marketplaceAvailable, configDir, skillsConfig, owner, rootVersion, registry, projectSkills, logger, verbose } = input;
558
687
  const pluginDir = getPluginOutputDir(configDir, marketplaceName, pluginDef.name);
559
688
  const pluginSourceDir = getPluginSourceDir(configDir, pluginDef);
560
689
  logger.info(` Building plugin: ${pluginDef.name}`);
@@ -621,9 +750,11 @@ async function buildPlugin(input) {
621
750
  skills: packageable,
622
751
  pluginDir,
623
752
  skillsConfig,
753
+ registry,
754
+ projectSkills,
624
755
  logger,
625
756
  });
626
- const skillsWithErrors = reportPackagedSkillIssues(packagedLocalSkills, logger);
757
+ const { withErrors: skillsWithErrors, issueCounts: localSkillIssueCounts } = reportPackagedSkillIssues(packagedLocalSkills, logger, verbose);
627
758
  if (skillsWithErrors.length > 0) {
628
759
  throw new Error(`Plugin '${pluginDef.name}': ${skillsWithErrors.length} plugin-local skill(s) emitted ` +
629
760
  `post-build validation errors: ${skillsWithErrors.join(', ')}`);
@@ -677,7 +808,7 @@ async function buildPlugin(input) {
677
808
  // truth that flows into both the merged plugin.json and marketplace.json.
678
809
  const authorJson = readAuthorPluginJson(pluginSourceDir);
679
810
  const pluginVersion = resolveVersion(pluginDef, authorJson, rootVersion, { warn: (message) => logger.info(`warning: ${message}`) });
680
- await writeMergedPluginJson(pluginDef, authorJson, pluginVersion, pluginDir, owner, logger);
811
+ const pluginAuthor = await writeMergedPluginJson(pluginDef, authorJson, pluginVersion, pluginDir, owner, logger);
681
812
  // Phase 6: per-plugin CHANGELOG copy. Resolves to <pluginSourceDir>/CHANGELOG.md
682
813
  // by default, or `entry.changelog` (relative to plugin source) when configured.
683
814
  // No-op when neither resolves — marketplace-level CHANGELOG (handled in
@@ -691,6 +822,7 @@ async function buildPlugin(input) {
691
822
  pluginName: pluginDef.name,
692
823
  pluginDir,
693
824
  pluginVersion,
825
+ pluginAuthor,
694
826
  skillsCopied,
695
827
  commandsCopied: treeResult.commandsCopied,
696
828
  hooksCopied: treeResult.hooksCopied,
@@ -699,6 +831,7 @@ async function buildPlugin(input) {
699
831
  treeFilesCopied: treeResult.filesCopied,
700
832
  explicitFilesCopied,
701
833
  localSkillsPackaged,
834
+ localSkillIssueCounts,
702
835
  };
703
836
  }
704
837
  //# sourceMappingURL=build.js.map