@vibe-agent-toolkit/cli 0.1.33 → 0.1.34

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 (68) hide show
  1. package/dist/bin.js +4 -0
  2. package/dist/bin.js.map +1 -1
  3. package/dist/commands/audit/git-url-clone.d.ts +32 -0
  4. package/dist/commands/audit/git-url-clone.d.ts.map +1 -0
  5. package/dist/commands/audit/git-url-clone.js +135 -0
  6. package/dist/commands/audit/git-url-clone.js.map +1 -0
  7. package/dist/commands/audit/hierarchical-output.js +2 -2
  8. package/dist/commands/audit/hierarchical-output.js.map +1 -1
  9. package/dist/commands/audit/provenance.d.ts +33 -0
  10. package/dist/commands/audit/provenance.d.ts.map +1 -0
  11. package/dist/commands/audit/provenance.js +57 -0
  12. package/dist/commands/audit/provenance.js.map +1 -0
  13. package/dist/commands/audit.d.ts.map +1 -1
  14. package/dist/commands/audit.js +257 -34
  15. package/dist/commands/audit.js.map +1 -1
  16. package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
  17. package/dist/commands/claude/marketplace/validate.js +2 -1
  18. package/dist/commands/claude/marketplace/validate.js.map +1 -1
  19. package/dist/commands/claude/plugin/build.d.ts +4 -3
  20. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  21. package/dist/commands/claude/plugin/build.js +178 -71
  22. package/dist/commands/claude/plugin/build.js.map +1 -1
  23. package/dist/commands/claude/plugin/plugin-files.d.ts +19 -0
  24. package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -0
  25. package/dist/commands/claude/plugin/plugin-files.js +53 -0
  26. package/dist/commands/claude/plugin/plugin-files.js.map +1 -0
  27. package/dist/commands/claude/plugin/plugin-json-merge.d.ts +29 -0
  28. package/dist/commands/claude/plugin/plugin-json-merge.d.ts.map +1 -0
  29. package/dist/commands/claude/plugin/plugin-json-merge.js +76 -0
  30. package/dist/commands/claude/plugin/plugin-json-merge.js.map +1 -0
  31. package/dist/commands/claude/plugin/plugin-validators.d.ts +13 -0
  32. package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -0
  33. package/dist/commands/claude/plugin/plugin-validators.js +59 -0
  34. package/dist/commands/claude/plugin/plugin-validators.js.map +1 -0
  35. package/dist/commands/claude/plugin/tree-copy.d.ts +23 -0
  36. package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -0
  37. package/dist/commands/claude/plugin/tree-copy.js +68 -0
  38. package/dist/commands/claude/plugin/tree-copy.js.map +1 -0
  39. package/dist/commands/corpus/index.d.ts +6 -0
  40. package/dist/commands/corpus/index.d.ts.map +1 -0
  41. package/dist/commands/corpus/index.js +53 -0
  42. package/dist/commands/corpus/index.js.map +1 -0
  43. package/dist/commands/corpus/report.d.ts +75 -0
  44. package/dist/commands/corpus/report.d.ts.map +1 -0
  45. package/dist/commands/corpus/report.js +83 -0
  46. package/dist/commands/corpus/report.js.map +1 -0
  47. package/dist/commands/corpus/runner.d.ts +24 -0
  48. package/dist/commands/corpus/runner.d.ts.map +1 -0
  49. package/dist/commands/corpus/runner.js +246 -0
  50. package/dist/commands/corpus/runner.js.map +1 -0
  51. package/dist/commands/corpus/scan.d.ts +15 -0
  52. package/dist/commands/corpus/scan.d.ts.map +1 -0
  53. package/dist/commands/corpus/scan.js +90 -0
  54. package/dist/commands/corpus/scan.js.map +1 -0
  55. package/dist/commands/corpus/seed.d.ts +178 -0
  56. package/dist/commands/corpus/seed.d.ts.map +1 -0
  57. package/dist/commands/corpus/seed.js +63 -0
  58. package/dist/commands/corpus/seed.js.map +1 -0
  59. package/dist/commands/inventory.d.ts +17 -0
  60. package/dist/commands/inventory.d.ts.map +1 -0
  61. package/dist/commands/inventory.js +90 -0
  62. package/dist/commands/inventory.js.map +1 -0
  63. package/dist/utils/git-url.d.ts +43 -0
  64. package/dist/utils/git-url.d.ts.map +1 -0
  65. package/dist/utils/git-url.js +135 -0
  66. package/dist/utils/git-url.js.map +1 -0
  67. package/docs/audit.md +60 -3
  68. package/package.json +11 -11
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Build-time validators for plugin declarations.
3
+ *
4
+ * - verifyPluginDirCaseMatch: guards against macOS/Windows case-insensitive FS drift
5
+ * (plugin: "foo-bar" -> plugins/Foo-Bar/ locally would break on Linux CI).
6
+ * - verifyNoCaseCollidingPluginNames: rejects pairs whose toLowerCase() collides.
7
+ * - parsePluginJsonFiles: parse-only JSON validation of hooks.json + .mcp.json
8
+ * (deep schema validation is Claude runtime's job).
9
+ */
10
+ import { existsSync } from 'node:fs';
11
+ import { readFile, readdir } from 'node:fs/promises';
12
+ import { safePath } from '@vibe-agent-toolkit/utils';
13
+ export async function verifyPluginDirCaseMatch(projectRoot, pluginName) {
14
+ const pluginsBase = safePath.join(projectRoot, 'plugins');
15
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
16
+ if (!existsSync(pluginsBase))
17
+ return;
18
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
19
+ const entries = await readdir(pluginsBase, { withFileTypes: true });
20
+ const matchInsensitive = entries.find((e) => e.isDirectory() && e.name.toLowerCase() === pluginName.toLowerCase());
21
+ if (matchInsensitive && matchInsensitive.name !== pluginName) {
22
+ throw new Error(`Plugin "${pluginName}" declared in config, but on-disk directory is "plugins/${matchInsensitive.name}/". ` +
23
+ `Names must match exactly (case-sensitive). This check catches macOS/Windows case-insensitive FS drift ` +
24
+ `that would break on Linux CI. Rename the directory or the config entry to match.`);
25
+ }
26
+ }
27
+ export function verifyNoCaseCollidingPluginNames(names) {
28
+ const seen = new Map();
29
+ for (const name of names) {
30
+ const key = name.toLowerCase();
31
+ const prior = seen.get(key);
32
+ if (prior === name) {
33
+ throw new Error(`Plugin name "${name}" is declared more than once across marketplaces. ` +
34
+ `Plugin names must be globally unique within a repo; rename one.`);
35
+ }
36
+ if (prior && prior !== name) {
37
+ throw new Error(`Plugin names "${prior}" and "${name}" differ only in case. ` +
38
+ `They would collide on case-insensitive filesystems; rename one.`);
39
+ }
40
+ seen.set(key, name);
41
+ }
42
+ }
43
+ async function parseJsonFileIfPresent(path, label) {
44
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved path
45
+ if (!existsSync(path))
46
+ return;
47
+ try {
48
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved path
49
+ JSON.parse(await readFile(path, 'utf-8'));
50
+ }
51
+ catch (e) {
52
+ throw new Error(`${label} is not valid JSON: ${e.message}`);
53
+ }
54
+ }
55
+ export async function parsePluginJsonFiles(pluginSourceDir) {
56
+ await parseJsonFileIfPresent(safePath.join(pluginSourceDir, 'hooks', 'hooks.json'), 'hooks/hooks.json');
57
+ await parseJsonFileIfPresent(safePath.join(pluginSourceDir, '.mcp.json'), '.mcp.json');
58
+ }
59
+ //# sourceMappingURL=plugin-validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-validators.js","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/plugin-validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,UAAkB;IAElB,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC1D,sFAAsF;IACtF,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO;IAErC,sFAAsF;IACtF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,WAAW,EAAE,CAC5E,CAAC;IACF,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,2DAA2D,gBAAgB,CAAC,IAAI,MAAM;YACzG,wGAAwG;YACxG,kFAAkF,CACrF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,KAAwB;IACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,oDAAoD;gBACtE,iEAAiE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,iBAAiB,KAAK,UAAU,IAAI,yBAAyB;gBAC3D,iEAAiE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,IAAY,EAAE,KAAa;IAC/D,oFAAoF;IACpF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,oFAAoF;QACpF,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,uBAAwB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,eAAuB;IAChE,MAAM,sBAAsB,CAC1B,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,CAAC,EACrD,kBAAkB,CACnB,CAAC;IACF,MAAM,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;AACzF,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Tree-copy stream for plugin build.
3
+ *
4
+ * Copies everything under <sourceDir> to <destDir>, except:
5
+ * - .claude-plugin/ (owned by plugin.json merge-write)
6
+ *
7
+ * Respects .gitignore via crawlDirectory (respectGitignore: true, the default).
8
+ * Returns counts keyed to the spec's YAML summary extension.
9
+ */
10
+ export interface TreeCopyOptions {
11
+ sourceDir: string;
12
+ destDir: string;
13
+ warn?: (message: string) => void;
14
+ }
15
+ export interface TreeCopyResult {
16
+ commandsCopied: number;
17
+ hooksCopied: number;
18
+ agentsCopied: number;
19
+ mcpCopied: number;
20
+ filesCopied: number;
21
+ }
22
+ export declare function treeCopyPlugin(options: TreeCopyOptions): Promise<TreeCopyResult>;
23
+ //# sourceMappingURL=tree-copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-copy.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/tree-copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAYD,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAiDtF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tree-copy stream for plugin build.
3
+ *
4
+ * Copies everything under <sourceDir> to <destDir>, except:
5
+ * - .claude-plugin/ (owned by plugin.json merge-write)
6
+ *
7
+ * Respects .gitignore via crawlDirectory (respectGitignore: true, the default).
8
+ * Returns counts keyed to the spec's YAML summary extension.
9
+ */
10
+ import { existsSync } from 'node:fs';
11
+ import { copyFile, mkdir } from 'node:fs/promises';
12
+ import { dirname } from 'node:path';
13
+ import { crawlDirectory, safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
14
+ const EXCLUDE_PATTERNS = ['.claude-plugin/**'];
15
+ function classifyRelative(rel) {
16
+ if (rel.startsWith('commands/'))
17
+ return 'commandsCopied';
18
+ if (rel.startsWith('hooks/'))
19
+ return 'hooksCopied';
20
+ if (rel.startsWith('agents/'))
21
+ return 'agentsCopied';
22
+ if (rel === '.mcp.json')
23
+ return 'mcpCopied';
24
+ return undefined;
25
+ }
26
+ export async function treeCopyPlugin(options) {
27
+ const { sourceDir, destDir, warn } = options;
28
+ const result = {
29
+ commandsCopied: 0,
30
+ hooksCopied: 0,
31
+ agentsCopied: 0,
32
+ mcpCopied: 0,
33
+ filesCopied: 0,
34
+ };
35
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- sourceDir resolved from config
36
+ if (!existsSync(sourceDir)) {
37
+ return result;
38
+ }
39
+ const authorMarketplaceJson = safePath.join(sourceDir, '.claude-plugin', 'marketplace.json');
40
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
41
+ if (existsSync(authorMarketplaceJson) && warn) {
42
+ warn(`Ignoring ${toForwardSlash(authorMarketplaceJson)}: marketplace.json is VAT-generated ` +
43
+ `at the marketplace level and cannot be supplied per-plugin.`);
44
+ }
45
+ const files = await crawlDirectory({
46
+ baseDir: sourceDir,
47
+ include: ['**/*'],
48
+ exclude: EXCLUDE_PATTERNS,
49
+ absolute: true,
50
+ filesOnly: true,
51
+ respectGitignore: true,
52
+ dot: true,
53
+ });
54
+ for (const absPath of files) {
55
+ const rel = toForwardSlash(safePath.relative(sourceDir, absPath));
56
+ const target = safePath.join(destDir, rel);
57
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- dest resolved from sourceDir+relative
58
+ await mkdir(dirname(target), { recursive: true });
59
+ await copyFile(absPath, target);
60
+ result.filesCopied += 1;
61
+ const bucket = classifyRelative(rel);
62
+ if (bucket) {
63
+ result[bucket] += 1;
64
+ }
65
+ }
66
+ return result;
67
+ }
68
+ //# sourceMappingURL=tree-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-copy.js","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/tree-copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAgBrF,MAAM,gBAAgB,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAE/C,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACzD,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,aAAa,CAAC;IACnD,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,cAAc,CAAC;IACrD,IAAI,GAAG,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB;IAC3D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,MAAM,GAAmB;QAC7B,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,CAAC;KACf,CAAC;IAEF,qGAAqG;IACrG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,qBAAqB,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;IAC7F,sFAAsF;IACtF,IAAI,UAAU,CAAC,qBAAqB,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9C,IAAI,CACF,YAAY,cAAc,CAAC,qBAAqB,CAAC,sCAAsC;YACrF,6DAA6D,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC;QACjC,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,OAAO,EAAE,gBAAgB;QACzB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI;QACf,gBAAgB,EAAE,IAAI;QACtB,GAAG,EAAE,IAAI;KACV,CAAC,CAAC;IAEH,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3C,4GAA4G;QAC5G,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;QAExB,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Corpus command group — Phase 1 ships only `scan`.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createCorpusCommand(): Command;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/corpus/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,mBAAmB,IAAI,OAAO,CAoD7C"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Corpus command group — Phase 1 ships only `scan`.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { corpusScanCommand } from './scan.js';
6
+ export function createCorpusCommand() {
7
+ const corpus = new Command('corpus');
8
+ corpus
9
+ .description('Run vat audit (and optionally vat skill review) at scale across a tracked plugin seed')
10
+ .helpCommand(false);
11
+ corpus
12
+ .command('scan [seed-file]')
13
+ .description('Audit each plugin in the seed; write a per-run snapshot under --out')
14
+ .argument('[seed-file]', 'Path to seed YAML (default: corpus/seed.yaml)')
15
+ .requiredOption('--out <dir>', 'Output directory for the run snapshot (no default — must be specified)')
16
+ .option('--with-review', 'Also invoke vat skill review per plugin (LLM-backed; uses API tokens)')
17
+ .option('--debug', 'Enable debug logging and preserve cloned tempdirs')
18
+ .action(async function (seedFile) {
19
+ await corpusScanCommand(seedFile, this.optsWithGlobals());
20
+ })
21
+ .addHelpText('after', `
22
+ Description:
23
+ Reads a seed YAML listing plugins to audit (each entry: { source, name,
24
+ validation? }), runs 'vat audit' against each (and optionally 'vat skill
25
+ review' with --with-review), writes summary.yaml plus per-plugin sibling
26
+ files into a date-sha subdirectory of --out.
27
+
28
+ source forms accepted (same as vat audit):
29
+ - local path (absolute or relative)
30
+ - https://host/owner/repo.git[#ref[:subpath]]
31
+ - GitHub web URL (https://github.com/owner/repo/tree/<ref>/<subpath>)
32
+ - GitHub shorthand (owner/repo, with optional #ref:subpath)
33
+ - SSH URL (git@host:owner/repo.git or ssh://...)
34
+ - file:// URL (local bare-repo testing)
35
+
36
+ Output:
37
+ <--out>/<UTC-date>-<vat-short-sha>/
38
+ summary.yaml # index: per-plugin status + totals
39
+ <name>-audit.yaml # full audit output per plugin
40
+ <name>-review.md # full skill-review output (only with --with-review)
41
+
42
+ Exit codes:
43
+ 0 - scan completed (regardless of unloadable plugins)
44
+ 2 - scan failed to start (seed missing, --out missing, etc.)
45
+ 130 - interrupted by SIGINT (partial results written)
46
+
47
+ Example:
48
+ $ vat corpus scan --out ~/scratch/vat-corpus-runs
49
+ $ vat corpus scan corpus/seed.yaml --out ~/scratch/vat-corpus-runs --with-review
50
+ `);
51
+ return corpus;
52
+ }
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/corpus/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAA0B,MAAM,WAAW,CAAC;AAEtE,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM;SACH,WAAW,CAAC,uFAAuF,CAAC;SACpG,WAAW,CAAC,KAAK,CAAC,CAAC;IAEtB,MAAM;SACH,OAAO,CAAC,kBAAkB,CAAC;SAC3B,WAAW,CAAC,qEAAqE,CAAC;SAClF,QAAQ,CAAC,aAAa,EAAE,+CAA+C,CAAC;SACxE,cAAc,CAAC,aAAa,EAAE,wEAAwE,CAAC;SACvG,MAAM,CAAC,eAAe,EAAE,uEAAuE,CAAC;SAChG,MAAM,CAAC,SAAS,EAAE,mDAAmD,CAAC;SACtE,MAAM,CAAC,KAAK,WAA0B,QAA4B;QACjE,MAAM,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAuB,CAAC,CAAC;IACjF,CAAC,CAAC;SACD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BL,CACI,CAAC;IAEJ,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Run-summary types + writer for `vat corpus scan`.
3
+ *
4
+ * `summary.yaml` is the index for one scan run. Per-plugin full audit
5
+ * outputs and full skill-review outputs are written as sibling files
6
+ * referenced by relative `output_path`. Totals are derived from the
7
+ * per-plugin rows so callers can pass raw rows and let this module
8
+ * compute aggregates.
9
+ */
10
+ export type AuditStatus = 'success' | 'warning' | 'error' | 'unloadable';
11
+ export type ReviewStatus = 'ok' | 'error' | 'skipped';
12
+ export interface AuditSummary {
13
+ errors: number;
14
+ warnings: number;
15
+ info: number;
16
+ files_scanned: number;
17
+ }
18
+ export interface AuditOutcome {
19
+ status: AuditStatus;
20
+ duration_ms: number;
21
+ summary?: AuditSummary;
22
+ findings_emitted?: number;
23
+ output_path?: string;
24
+ error?: string;
25
+ }
26
+ export interface ReviewOutcome {
27
+ status: ReviewStatus;
28
+ duration_ms: number;
29
+ output_path?: string;
30
+ error?: string;
31
+ }
32
+ export interface PluginRow {
33
+ source: string;
34
+ name: string;
35
+ validation_applied: boolean;
36
+ audit: AuditOutcome;
37
+ review: ReviewOutcome;
38
+ }
39
+ export interface RunReport {
40
+ schema_version: 1;
41
+ generated_at: string;
42
+ vat_version: string;
43
+ vat_commit: string;
44
+ seed_file: string;
45
+ flags: {
46
+ with_review: boolean;
47
+ debug: boolean;
48
+ };
49
+ plugins: PluginRow[];
50
+ }
51
+ export interface RunTotals {
52
+ plugins: number;
53
+ audit_clean: number;
54
+ audit_warning: number;
55
+ audit_error: number;
56
+ unloadable: number;
57
+ reviewed?: number;
58
+ }
59
+ /**
60
+ * Compute totals over the per-plugin rows.
61
+ */
62
+ export declare function computeTotals(report: RunReport): RunTotals;
63
+ /**
64
+ * Build the run directory name: `<YYYY-MM-DD>-<vat-short-sha>`.
65
+ * Date is the UTC date of `generated_at`.
66
+ */
67
+ export declare function runDirectoryName(report: RunReport): string;
68
+ /**
69
+ * Write `summary.yaml` (and create the run directory) under `outDir`.
70
+ * Returns the absolute path of the created run directory. Per-plugin
71
+ * sibling files (audit outputs, review outputs) are written by the
72
+ * runner — this function only writes the summary index.
73
+ */
74
+ export declare function writeRunReport(report: RunReport, outDir: string): Promise<string>;
75
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/commands/corpus/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,cAAc,EAAE,CAAC,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAmC1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAG1D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBvF"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Run-summary types + writer for `vat corpus scan`.
3
+ *
4
+ * `summary.yaml` is the index for one scan run. Per-plugin full audit
5
+ * outputs and full skill-review outputs are written as sibling files
6
+ * referenced by relative `output_path`. Totals are derived from the
7
+ * per-plugin rows so callers can pass raw rows and let this module
8
+ * compute aggregates.
9
+ */
10
+ import { mkdirSync, writeFileSync } from 'node:fs';
11
+ import { safePath } from '@vibe-agent-toolkit/utils';
12
+ import * as yaml from 'js-yaml';
13
+ /**
14
+ * Compute totals over the per-plugin rows.
15
+ */
16
+ export function computeTotals(report) {
17
+ const totals = {
18
+ plugins: report.plugins.length,
19
+ audit_clean: 0,
20
+ audit_warning: 0,
21
+ audit_error: 0,
22
+ unloadable: 0,
23
+ };
24
+ for (const row of report.plugins) {
25
+ switch (row.audit.status) {
26
+ case 'success': {
27
+ totals.audit_clean += 1;
28
+ break;
29
+ }
30
+ case 'warning': {
31
+ totals.audit_warning += 1;
32
+ break;
33
+ }
34
+ case 'error': {
35
+ totals.audit_error += 1;
36
+ break;
37
+ }
38
+ case 'unloadable': {
39
+ totals.unloadable += 1;
40
+ break;
41
+ }
42
+ }
43
+ }
44
+ if (report.flags.with_review) {
45
+ totals.reviewed = report.plugins.filter((p) => p.review.status !== 'skipped').length;
46
+ }
47
+ return totals;
48
+ }
49
+ /**
50
+ * Build the run directory name: `<YYYY-MM-DD>-<vat-short-sha>`.
51
+ * Date is the UTC date of `generated_at`.
52
+ */
53
+ export function runDirectoryName(report) {
54
+ const datePart = report.generated_at.slice(0, 10); // 'YYYY-MM-DD'
55
+ return `${datePart}-${report.vat_commit}`;
56
+ }
57
+ /**
58
+ * Write `summary.yaml` (and create the run directory) under `outDir`.
59
+ * Returns the absolute path of the created run directory. Per-plugin
60
+ * sibling files (audit outputs, review outputs) are written by the
61
+ * runner — this function only writes the summary index.
62
+ */
63
+ export async function writeRunReport(report, outDir) {
64
+ const runDir = safePath.join(outDir, runDirectoryName(report));
65
+ // eslint-disable-next-line local/no-fs-mkdirSync, security/detect-non-literal-fs-filename -- the corpus output dir is caller-supplied; mkdir-recursive is the right call here
66
+ mkdirSync(runDir, { recursive: true });
67
+ const totals = computeTotals(report);
68
+ const dump = {
69
+ schema_version: report.schema_version,
70
+ generated_at: report.generated_at,
71
+ vat_version: report.vat_version,
72
+ vat_commit: report.vat_commit,
73
+ seed_file: report.seed_file,
74
+ flags: report.flags,
75
+ plugins: report.plugins,
76
+ totals,
77
+ };
78
+ const summaryPath = safePath.join(runDir, 'summary.yaml');
79
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- summaryPath composed under our run dir
80
+ writeFileSync(summaryPath, yaml.dump(dump, { lineWidth: -1 }), 'utf-8');
81
+ return runDir;
82
+ }
83
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/corpus/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAuDhC;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC7C,MAAM,MAAM,GAAc;QACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;QAC9B,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,CAAC;QAChB,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,CAAC;KACd,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjC,QAAQ,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACzB,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;gBACxB,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC;gBAC1B,MAAM;YACR,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;gBACxB,MAAM;YACR,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;gBACvB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IACvF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe;IAClE,OAAO,GAAG,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAiB,EAAE,MAAc;IACpE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,8KAA8K;IAC9K,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG;QACX,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM;KACP,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1D,6GAA6G;IAC7G,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAExE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Per-plugin orchestrator for `vat corpus scan`.
3
+ *
4
+ * Phase 1 scope: resolve source (local or URL), optionally overlay a
5
+ * synthetic `vibe-agent-toolkit.config.yaml` from the entry's `validation:`
6
+ * block, run `vat audit` in-process, optionally invoke `vat skill review`,
7
+ * write per-plugin sibling files into the run directory, and return a
8
+ * PluginRow. Per-plugin failures never abort the loop.
9
+ *
10
+ * URL handling clones via Layer 1's `withClonedRepo` helper. Validation
11
+ * overlay (Task 5) is added on top of this base.
12
+ */
13
+ import type { PluginRow } from './report.js';
14
+ import type { PluginEntry } from './seed.js';
15
+ export interface RunnerOptions {
16
+ runDir: string;
17
+ withReview: boolean;
18
+ debug: boolean;
19
+ }
20
+ /**
21
+ * Run audit + optional review against one plugin entry.
22
+ */
23
+ export declare function auditOnePlugin(entry: PluginEntry, opts: RunnerOptions): Promise<PluginRow>;
24
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/commands/corpus/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH,OAAO,KAAK,EAA2C,SAAS,EAAiB,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAqB7C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB;AA0BD;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,SAAS,CAAC,CAKpB"}