@vibe-agent-toolkit/cli 0.2.0-rc.10 → 0.2.0-rc.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/bin/supervise-cli.d.ts +45 -0
- package/dist/bin/supervise-cli.d.ts.map +1 -0
- package/dist/bin/supervise-cli.js +83 -0
- package/dist/bin/supervise-cli.js.map +1 -0
- package/dist/bin/vat +94 -40
- package/dist/bin/vat.d.ts +15 -4
- package/dist/bin/vat.d.ts.map +1 -1
- package/dist/bin/vat.js +94 -40
- package/dist/bin/vat.js.map +1 -1
- package/dist/bin.js +21 -29
- package/dist/bin.js.map +1 -1
- package/dist/command-tree.d.ts +45 -0
- package/dist/command-tree.d.ts.map +1 -0
- package/dist/command-tree.js +60 -0
- package/dist/command-tree.js.map +1 -0
- package/dist/commands/agent/build-schema.d.ts +100 -0
- package/dist/commands/agent/build-schema.d.ts.map +1 -0
- package/dist/commands/agent/build-schema.js +32 -0
- package/dist/commands/agent/build-schema.js.map +1 -0
- package/dist/commands/agent/build.d.ts +1 -0
- package/dist/commands/agent/build.d.ts.map +1 -1
- package/dist/commands/agent/build.js +63 -33
- package/dist/commands/agent/build.js.map +1 -1
- package/dist/commands/agent/import-schema.d.ts +75 -0
- package/dist/commands/agent/import-schema.d.ts.map +1 -0
- package/dist/commands/agent/import-schema.js +25 -0
- package/dist/commands/agent/import-schema.js.map +1 -0
- package/dist/commands/agent/import.d.ts.map +1 -1
- package/dist/commands/agent/import.js +33 -27
- package/dist/commands/agent/import.js.map +1 -1
- package/dist/commands/agent/index.d.ts.map +1 -1
- package/dist/commands/agent/index.js +132 -37
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/agent/install-path.d.ts.map +1 -1
- package/dist/commands/agent/install-path.js +2 -1
- package/dist/commands/agent/install-path.js.map +1 -1
- package/dist/commands/agent/install-schema.d.ts +89 -0
- package/dist/commands/agent/install-schema.d.ts.map +1 -0
- package/dist/commands/agent/install-schema.js +29 -0
- package/dist/commands/agent/install-schema.js.map +1 -0
- package/dist/commands/agent/install.d.ts +7 -1
- package/dist/commands/agent/install.d.ts.map +1 -1
- package/dist/commands/agent/install.js +78 -108
- package/dist/commands/agent/install.js.map +1 -1
- package/dist/commands/agent/installed-schema.d.ts +140 -0
- package/dist/commands/agent/installed-schema.d.ts.map +1 -0
- package/dist/commands/agent/installed-schema.js +36 -0
- package/dist/commands/agent/installed-schema.js.map +1 -0
- package/dist/commands/agent/installed.d.ts +1 -1
- package/dist/commands/agent/installed.d.ts.map +1 -1
- package/dist/commands/agent/installed.js +104 -75
- package/dist/commands/agent/installed.js.map +1 -1
- package/dist/commands/agent/list-schema.d.ts +128 -0
- package/dist/commands/agent/list-schema.d.ts.map +1 -0
- package/dist/commands/agent/list-schema.js +34 -0
- package/dist/commands/agent/list-schema.js.map +1 -0
- package/dist/commands/agent/list.d.ts +4 -3
- package/dist/commands/agent/list.d.ts.map +1 -1
- package/dist/commands/agent/list.js +50 -37
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/run.d.ts +3 -0
- package/dist/commands/agent/run.d.ts.map +1 -1
- package/dist/commands/agent/run.js +8 -3
- package/dist/commands/agent/run.js.map +1 -1
- package/dist/commands/agent/uninstall-schema.d.ts +89 -0
- package/dist/commands/agent/uninstall-schema.d.ts.map +1 -0
- package/dist/commands/agent/uninstall-schema.js +29 -0
- package/dist/commands/agent/uninstall-schema.js.map +1 -0
- package/dist/commands/agent/uninstall.d.ts +5 -1
- package/dist/commands/agent/uninstall.d.ts.map +1 -1
- package/dist/commands/agent/uninstall.js +50 -38
- package/dist/commands/agent/uninstall.js.map +1 -1
- package/dist/commands/agent/validate-schema.d.ts +129 -0
- package/dist/commands/agent/validate-schema.d.ts.map +1 -0
- package/dist/commands/agent/validate-schema.js +35 -0
- package/dist/commands/agent/validate-schema.js.map +1 -0
- package/dist/commands/agent/validate.d.ts +6 -0
- package/dist/commands/agent/validate.d.ts.map +1 -1
- package/dist/commands/agent/validate.js +64 -36
- package/dist/commands/agent/validate.js.map +1 -1
- package/dist/commands/ard/emit-schema.d.ts +108 -0
- package/dist/commands/ard/emit-schema.d.ts.map +1 -0
- package/dist/commands/ard/emit-schema.js +37 -0
- package/dist/commands/ard/emit-schema.js.map +1 -0
- package/dist/commands/ard/emit.d.ts +31 -63
- package/dist/commands/ard/emit.d.ts.map +1 -1
- package/dist/commands/ard/emit.js +124 -68
- package/dist/commands/ard/emit.js.map +1 -1
- package/dist/commands/ard/index.d.ts.map +1 -1
- package/dist/commands/ard/index.js +17 -10
- package/dist/commands/ard/index.js.map +1 -1
- package/dist/commands/audit/compat-lane-findings.d.ts +65 -0
- package/dist/commands/audit/compat-lane-findings.d.ts.map +1 -0
- package/dist/commands/audit/compat-lane-findings.js +72 -0
- package/dist/commands/audit/compat-lane-findings.js.map +1 -0
- package/dist/commands/audit/distributed-tree.d.ts +2 -2
- package/dist/commands/audit/distributed-tree.d.ts.map +1 -1
- package/dist/commands/audit/distributed-tree.js +23 -12
- package/dist/commands/audit/distributed-tree.js.map +1 -1
- package/dist/commands/audit/git-url-clone.d.ts +15 -7
- package/dist/commands/audit/git-url-clone.d.ts.map +1 -1
- package/dist/commands/audit/git-url-clone.js +85 -42
- package/dist/commands/audit/git-url-clone.js.map +1 -1
- package/dist/commands/audit/hierarchical-output.d.ts +28 -4
- package/dist/commands/audit/hierarchical-output.d.ts.map +1 -1
- package/dist/commands/audit/hierarchical-output.js +44 -27
- package/dist/commands/audit/hierarchical-output.js.map +1 -1
- package/dist/commands/audit/scan-population.d.ts.map +1 -1
- package/dist/commands/audit/scan-population.js +2 -1
- package/dist/commands/audit/scan-population.js.map +1 -1
- package/dist/commands/audit-schema.d.ts +1247 -0
- package/dist/commands/audit-schema.d.ts.map +1 -0
- package/dist/commands/audit-schema.js +139 -0
- package/dist/commands/audit-schema.js.map +1 -0
- package/dist/commands/audit-settings-schema.d.ts +417 -0
- package/dist/commands/audit-settings-schema.d.ts.map +1 -0
- package/dist/commands/audit-settings-schema.js +77 -0
- package/dist/commands/audit-settings-schema.js.map +1 -0
- package/dist/commands/audit-settings.d.ts +28 -9
- package/dist/commands/audit-settings.d.ts.map +1 -1
- package/dist/commands/audit-settings.js +215 -151
- package/dist/commands/audit-settings.js.map +1 -1
- package/dist/commands/audit.d.ts +72 -33
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +415 -397
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/build.d.ts +61 -4
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +176 -190
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cache/clear-schema.d.ts +111 -0
- package/dist/commands/cache/clear-schema.d.ts.map +1 -0
- package/dist/commands/cache/clear-schema.js +37 -0
- package/dist/commands/cache/clear-schema.js.map +1 -0
- package/dist/commands/cache/clear.d.ts +28 -26
- package/dist/commands/cache/clear.d.ts.map +1 -1
- package/dist/commands/cache/clear.js +108 -103
- package/dist/commands/cache/clear.js.map +1 -1
- package/dist/commands/cache/index.d.ts.map +1 -1
- package/dist/commands/cache/index.js +13 -7
- package/dist/commands/cache/index.js.map +1 -1
- package/dist/commands/claude/claude-config.d.ts +23 -6
- package/dist/commands/claude/claude-config.d.ts.map +1 -1
- package/dist/commands/claude/claude-config.js +29 -15
- package/dist/commands/claude/claude-config.js.map +1 -1
- package/dist/commands/claude/context.d.ts +87 -2
- package/dist/commands/claude/context.d.ts.map +1 -1
- package/dist/commands/claude/context.js +116 -57
- package/dist/commands/claude/context.js.map +1 -1
- package/dist/commands/claude/marketplace/changelog-utils.js +2 -2
- package/dist/commands/claude/marketplace/changelog-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts +14 -1
- package/dist/commands/claude/marketplace/git-publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/git-publish.js +135 -68
- package/dist/commands/claude/marketplace/git-publish.js.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.d.ts +3 -5
- package/dist/commands/claude/marketplace/license-utils.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/license-utils.js +16 -7
- package/dist/commands/claude/marketplace/license-utils.js.map +1 -1
- package/dist/commands/claude/marketplace/publish-schema.d.ts +137 -0
- package/dist/commands/claude/marketplace/publish-schema.d.ts.map +1 -0
- package/dist/commands/claude/marketplace/publish-schema.js +32 -0
- package/dist/commands/claude/marketplace/publish-schema.js.map +1 -0
- package/dist/commands/claude/marketplace/publish-tree.d.ts +6 -0
- package/dist/commands/claude/marketplace/publish-tree.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish-tree.js +75 -17
- package/dist/commands/claude/marketplace/publish-tree.js.map +1 -1
- package/dist/commands/claude/marketplace/publish.d.ts +27 -0
- package/dist/commands/claude/marketplace/publish.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/publish.js +84 -50
- package/dist/commands/claude/marketplace/publish.js.map +1 -1
- package/dist/commands/claude/marketplace/validate-schema.d.ts +362 -0
- package/dist/commands/claude/marketplace/validate-schema.d.ts.map +1 -0
- package/dist/commands/claude/marketplace/validate-schema.js +67 -0
- package/dist/commands/claude/marketplace/validate-schema.js.map +1 -0
- package/dist/commands/claude/marketplace/validate.d.ts +40 -53
- package/dist/commands/claude/marketplace/validate.d.ts.map +1 -1
- package/dist/commands/claude/marketplace/validate.js +358 -214
- package/dist/commands/claude/marketplace/validate.js.map +1 -1
- package/dist/commands/claude/org/api-keys.d.ts +3 -0
- package/dist/commands/claude/org/api-keys.d.ts.map +1 -1
- package/dist/commands/claude/org/api-keys.js +4 -5
- package/dist/commands/claude/org/api-keys.js.map +1 -1
- package/dist/commands/claude/org/code-analytics.js +1 -1
- package/dist/commands/claude/org/code-analytics.js.map +1 -1
- package/dist/commands/claude/org/cost.d.ts.map +1 -1
- package/dist/commands/claude/org/cost.js +11 -33
- package/dist/commands/claude/org/cost.js.map +1 -1
- package/dist/commands/claude/org/helpers.d.ts +40 -27
- package/dist/commands/claude/org/helpers.d.ts.map +1 -1
- package/dist/commands/claude/org/helpers.js +61 -66
- package/dist/commands/claude/org/helpers.js.map +1 -1
- package/dist/commands/claude/org/index.d.ts.map +1 -1
- package/dist/commands/claude/org/index.js +10 -4
- package/dist/commands/claude/org/index.js.map +1 -1
- package/dist/commands/claude/org/info.d.ts.map +1 -1
- package/dist/commands/claude/org/info.js +2 -3
- package/dist/commands/claude/org/info.js.map +1 -1
- package/dist/commands/claude/org/invites.d.ts +3 -0
- package/dist/commands/claude/org/invites.d.ts.map +1 -1
- package/dist/commands/claude/org/invites.js +5 -7
- package/dist/commands/claude/org/invites.js.map +1 -1
- package/dist/commands/claude/org/skills.d.ts +76 -21
- package/dist/commands/claude/org/skills.d.ts.map +1 -1
- package/dist/commands/claude/org/skills.js +273 -246
- package/dist/commands/claude/org/skills.js.map +1 -1
- package/dist/commands/claude/org/stubs-schema.d.ts +56 -0
- package/dist/commands/claude/org/stubs-schema.d.ts.map +1 -0
- package/dist/commands/claude/org/stubs-schema.js +23 -0
- package/dist/commands/claude/org/stubs-schema.js.map +1 -0
- package/dist/commands/claude/org/stubs.d.ts +8 -3
- package/dist/commands/claude/org/stubs.d.ts.map +1 -1
- package/dist/commands/claude/org/stubs.js +9 -9
- package/dist/commands/claude/org/stubs.js.map +1 -1
- package/dist/commands/claude/org/usage.d.ts.map +1 -1
- package/dist/commands/claude/org/usage.js +1 -2
- package/dist/commands/claude/org/usage.js.map +1 -1
- package/dist/commands/claude/org/users.d.ts +3 -0
- package/dist/commands/claude/org/users.d.ts.map +1 -1
- package/dist/commands/claude/org/users.js +6 -8
- package/dist/commands/claude/org/users.js.map +1 -1
- package/dist/commands/claude/org/workspaces.d.ts +3 -0
- package/dist/commands/claude/org/workspaces.d.ts.map +1 -1
- package/dist/commands/claude/org/workspaces.js +10 -15
- package/dist/commands/claude/org/workspaces.js.map +1 -1
- package/dist/commands/claude/plugin/build-schema.d.ts +642 -0
- package/dist/commands/claude/plugin/build-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/build-schema.js +51 -0
- package/dist/commands/claude/plugin/build-schema.js.map +1 -0
- package/dist/commands/claude/plugin/build.d.ts +220 -45
- package/dist/commands/claude/plugin/build.d.ts.map +1 -1
- package/dist/commands/claude/plugin/build.js +466 -249
- package/dist/commands/claude/plugin/build.js.map +1 -1
- package/dist/commands/claude/plugin/helpers.d.ts +186 -24
- package/dist/commands/claude/plugin/helpers.d.ts.map +1 -1
- package/dist/commands/claude/plugin/helpers.js +110 -68
- package/dist/commands/claude/plugin/helpers.js.map +1 -1
- package/dist/commands/claude/plugin/install-schema.d.ts +144 -0
- package/dist/commands/claude/plugin/install-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/install-schema.js +36 -0
- package/dist/commands/claude/plugin/install-schema.js.map +1 -0
- package/dist/commands/claude/plugin/install.d.ts +191 -11
- package/dist/commands/claude/plugin/install.d.ts.map +1 -1
- package/dist/commands/claude/plugin/install.js +688 -628
- package/dist/commands/claude/plugin/install.js.map +1 -1
- package/dist/commands/claude/plugin/kept-findings.d.ts +19 -0
- package/dist/commands/claude/plugin/kept-findings.d.ts.map +1 -0
- package/dist/commands/claude/plugin/kept-findings.js +24 -0
- package/dist/commands/claude/plugin/kept-findings.js.map +1 -0
- package/dist/commands/claude/plugin/list-schema.d.ts +223 -0
- package/dist/commands/claude/plugin/list-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/list-schema.js +34 -0
- package/dist/commands/claude/plugin/list-schema.js.map +1 -0
- package/dist/commands/claude/plugin/list.d.ts +18 -0
- package/dist/commands/claude/plugin/list.d.ts.map +1 -1
- package/dist/commands/claude/plugin/list.js +53 -45
- package/dist/commands/claude/plugin/list.js.map +1 -1
- package/dist/commands/claude/plugin/npm-pack.d.ts +15 -0
- package/dist/commands/claude/plugin/npm-pack.d.ts.map +1 -0
- package/dist/commands/claude/plugin/npm-pack.js +39 -0
- package/dist/commands/claude/plugin/npm-pack.js.map +1 -0
- package/dist/commands/claude/plugin/plugin-changelog.d.ts +5 -1
- package/dist/commands/claude/plugin/plugin-changelog.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-changelog.js +9 -5
- package/dist/commands/claude/plugin/plugin-changelog.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.d.ts +21 -2
- package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-files.js +65 -32
- package/dist/commands/claude/plugin/plugin-files.js.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.d.ts +13 -0
- package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -1
- package/dist/commands/claude/plugin/plugin-validators.js +64 -16
- package/dist/commands/claude/plugin/plugin-validators.js.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -1
- package/dist/commands/claude/plugin/tree-copy.js +63 -37
- package/dist/commands/claude/plugin/tree-copy.js.map +1 -1
- package/dist/commands/claude/plugin/uninstall-schema.d.ts +112 -0
- package/dist/commands/claude/plugin/uninstall-schema.d.ts.map +1 -0
- package/dist/commands/claude/plugin/uninstall-schema.js +28 -0
- package/dist/commands/claude/plugin/uninstall-schema.js.map +1 -0
- package/dist/commands/claude/plugin/uninstall.d.ts +57 -0
- package/dist/commands/claude/plugin/uninstall.d.ts.map +1 -1
- package/dist/commands/claude/plugin/uninstall.js +176 -64
- package/dist/commands/claude/plugin/uninstall.js.map +1 -1
- package/dist/commands/consistency-check.d.ts.map +1 -1
- package/dist/commands/consistency-check.js +8 -6
- package/dist/commands/consistency-check.js.map +1 -1
- package/dist/commands/corpus/index.d.ts.map +1 -1
- package/dist/commands/corpus/index.js +26 -10
- package/dist/commands/corpus/index.js.map +1 -1
- package/dist/commands/corpus/report.d.ts +34 -16
- package/dist/commands/corpus/report.d.ts.map +1 -1
- package/dist/commands/corpus/report.js +36 -18
- package/dist/commands/corpus/report.js.map +1 -1
- package/dist/commands/corpus/runner.d.ts +25 -20
- package/dist/commands/corpus/runner.d.ts.map +1 -1
- package/dist/commands/corpus/runner.js +123 -67
- package/dist/commands/corpus/runner.js.map +1 -1
- package/dist/commands/corpus/scan-schema.d.ts +127 -0
- package/dist/commands/corpus/scan-schema.d.ts.map +1 -0
- package/dist/commands/corpus/scan-schema.js +31 -0
- package/dist/commands/corpus/scan-schema.js.map +1 -0
- package/dist/commands/corpus/scan.d.ts +31 -0
- package/dist/commands/corpus/scan.d.ts.map +1 -1
- package/dist/commands/corpus/scan.js +124 -50
- package/dist/commands/corpus/scan.js.map +1 -1
- package/dist/commands/corpus/seed.d.ts +11 -8
- package/dist/commands/corpus/seed.d.ts.map +1 -1
- package/dist/commands/corpus/seed.js +29 -11
- package/dist/commands/corpus/seed.js.map +1 -1
- package/dist/commands/doctor-render.d.ts +52 -0
- package/dist/commands/doctor-render.d.ts.map +1 -0
- package/dist/commands/doctor-render.js +110 -0
- package/dist/commands/doctor-render.js.map +1 -0
- package/dist/commands/doctor-schema.d.ts +191 -0
- package/dist/commands/doctor-schema.d.ts.map +1 -0
- package/dist/commands/doctor-schema.js +44 -0
- package/dist/commands/doctor-schema.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -62
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +126 -165
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/inventory-schema.d.ts +7297 -0
- package/dist/commands/inventory-schema.d.ts.map +1 -0
- package/dist/commands/inventory-schema.js +28 -0
- package/dist/commands/inventory-schema.js.map +1 -0
- package/dist/commands/inventory.d.ts +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +89 -41
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/mcp/index.d.ts.map +1 -1
- package/dist/commands/mcp/index.js +15 -0
- package/dist/commands/mcp/index.js.map +1 -1
- package/dist/commands/mcp/list-collections-schema.d.ts +101 -0
- package/dist/commands/mcp/list-collections-schema.d.ts.map +1 -0
- package/dist/commands/mcp/list-collections-schema.js +22 -0
- package/dist/commands/mcp/list-collections-schema.js.map +1 -0
- package/dist/commands/mcp/list-collections.d.ts +1 -1
- package/dist/commands/mcp/list-collections.d.ts.map +1 -1
- package/dist/commands/mcp/list-collections.js +19 -17
- package/dist/commands/mcp/list-collections.js.map +1 -1
- package/dist/commands/mcp/serve.d.ts +5 -0
- package/dist/commands/mcp/serve.d.ts.map +1 -1
- package/dist/commands/mcp/serve.js +29 -15
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/okf/index.d.ts.map +1 -1
- package/dist/commands/okf/index.js +13 -10
- package/dist/commands/okf/index.js.map +1 -1
- package/dist/commands/okf/validate-schema.d.ts +171 -0
- package/dist/commands/okf/validate-schema.d.ts.map +1 -0
- package/dist/commands/okf/validate-schema.js +44 -0
- package/dist/commands/okf/validate-schema.js.map +1 -0
- package/dist/commands/okf/validate.d.ts +16 -145
- package/dist/commands/okf/validate.d.ts.map +1 -1
- package/dist/commands/okf/validate.js +63 -52
- package/dist/commands/okf/validate.js.map +1 -1
- package/dist/commands/orchestrator-schema.d.ts +419 -0
- package/dist/commands/orchestrator-schema.d.ts.map +1 -0
- package/dist/commands/orchestrator-schema.js +91 -0
- package/dist/commands/orchestrator-schema.js.map +1 -0
- package/dist/commands/phase-utils.d.ts +188 -220
- package/dist/commands/phase-utils.d.ts.map +1 -1
- package/dist/commands/phase-utils.js +210 -258
- package/dist/commands/phase-utils.js.map +1 -1
- package/dist/commands/positional-args.d.ts +13 -11
- package/dist/commands/positional-args.d.ts.map +1 -1
- package/dist/commands/positional-args.js +16 -15
- package/dist/commands/positional-args.js.map +1 -1
- package/dist/commands/rag/admin-schema.d.ts +152 -0
- package/dist/commands/rag/admin-schema.d.ts.map +1 -0
- package/dist/commands/rag/admin-schema.js +31 -0
- package/dist/commands/rag/admin-schema.js.map +1 -0
- package/dist/commands/rag/clear-command.d.ts.map +1 -1
- package/dist/commands/rag/clear-command.js +30 -15
- package/dist/commands/rag/clear-command.js.map +1 -1
- package/dist/commands/rag/command-helpers.d.ts +31 -7
- package/dist/commands/rag/command-helpers.d.ts.map +1 -1
- package/dist/commands/rag/command-helpers.js +41 -21
- package/dist/commands/rag/command-helpers.js.map +1 -1
- package/dist/commands/rag/index-command.d.ts +37 -48
- package/dist/commands/rag/index-command.d.ts.map +1 -1
- package/dist/commands/rag/index-command.js +80 -65
- package/dist/commands/rag/index-command.js.map +1 -1
- package/dist/commands/rag/index-schema.d.ts +107 -0
- package/dist/commands/rag/index-schema.d.ts.map +1 -0
- package/dist/commands/rag/index-schema.js +34 -0
- package/dist/commands/rag/index-schema.js.map +1 -0
- package/dist/commands/rag/index.d.ts.map +1 -1
- package/dist/commands/rag/index.js +88 -41
- package/dist/commands/rag/index.js.map +1 -1
- package/dist/commands/rag/query-command.d.ts +18 -4
- package/dist/commands/rag/query-command.d.ts.map +1 -1
- package/dist/commands/rag/query-command.js +42 -27
- package/dist/commands/rag/query-command.js.map +1 -1
- package/dist/commands/rag/query-schema.d.ts +363 -0
- package/dist/commands/rag/query-schema.d.ts.map +1 -0
- package/dist/commands/rag/query-schema.js +59 -0
- package/dist/commands/rag/query-schema.js.map +1 -0
- package/dist/commands/rag/stats-command.d.ts.map +1 -1
- package/dist/commands/rag/stats-command.js +19 -18
- package/dist/commands/rag/stats-command.js.map +1 -1
- package/dist/commands/resources/check-progress.d.ts +79 -13
- package/dist/commands/resources/check-progress.d.ts.map +1 -1
- package/dist/commands/resources/check-progress.js +112 -11
- package/dist/commands/resources/check-progress.js.map +1 -1
- package/dist/commands/resources/check-schema.d.ts +335 -0
- package/dist/commands/resources/check-schema.d.ts.map +1 -0
- package/dist/commands/resources/check-schema.js +104 -0
- package/dist/commands/resources/check-schema.js.map +1 -0
- package/dist/commands/resources/check-supervisor.d.ts +329 -71
- package/dist/commands/resources/check-supervisor.d.ts.map +1 -1
- package/dist/commands/resources/check-supervisor.js +507 -107
- package/dist/commands/resources/check-supervisor.js.map +1 -1
- package/dist/commands/resources/check.d.ts +88 -254
- package/dist/commands/resources/check.d.ts.map +1 -1
- package/dist/commands/resources/check.js +537 -310
- package/dist/commands/resources/check.js.map +1 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +189 -103
- package/dist/commands/resources/index.js.map +1 -1
- package/dist/commands/resources/query-schema.d.ts +188 -0
- package/dist/commands/resources/query-schema.d.ts.map +1 -0
- package/dist/commands/resources/query-schema.js +48 -0
- package/dist/commands/resources/query-schema.js.map +1 -0
- package/dist/commands/resources/query.d.ts +18 -13
- package/dist/commands/resources/query.d.ts.map +1 -1
- package/dist/commands/resources/query.js +61 -49
- package/dist/commands/resources/query.js.map +1 -1
- package/dist/commands/resources/scan-schema.d.ts +195 -0
- package/dist/commands/resources/scan-schema.d.ts.map +1 -0
- package/dist/commands/resources/scan-schema.js +53 -0
- package/dist/commands/resources/scan-schema.js.map +1 -0
- package/dist/commands/resources/scan.d.ts +26 -3
- package/dist/commands/resources/scan.d.ts.map +1 -1
- package/dist/commands/resources/scan.js +51 -53
- package/dist/commands/resources/scan.js.map +1 -1
- package/dist/commands/resources/validate-schema.d.ts +326 -0
- package/dist/commands/resources/validate-schema.d.ts.map +1 -0
- package/dist/commands/resources/validate-schema.js +60 -0
- package/dist/commands/resources/validate-schema.js.map +1 -0
- package/dist/commands/resources/validate.d.ts +45 -169
- package/dist/commands/resources/validate.d.ts.map +1 -1
- package/dist/commands/resources/validate.js +221 -485
- package/dist/commands/resources/validate.js.map +1 -1
- package/dist/commands/skill/review-checklist.d.ts.map +1 -1
- package/dist/commands/skill/review-checklist.js +0 -1
- package/dist/commands/skill/review-checklist.js.map +1 -1
- package/dist/commands/skill/review-schema.d.ts +278 -0
- package/dist/commands/skill/review-schema.d.ts.map +1 -0
- package/dist/commands/skill/review-schema.js +46 -0
- package/dist/commands/skill/review-schema.js.map +1 -0
- package/dist/commands/skill/review.d.ts +8 -234
- package/dist/commands/skill/review.d.ts.map +1 -1
- package/dist/commands/skill/review.js +54 -77
- package/dist/commands/skill/review.js.map +1 -1
- package/dist/commands/skill/test/auth-flags.d.ts +3 -0
- package/dist/commands/skill/test/auth-flags.d.ts.map +1 -1
- package/dist/commands/skill/test/auth-flags.js +6 -2
- package/dist/commands/skill/test/auth-flags.js.map +1 -1
- package/dist/commands/skill/test/configure-schema.d.ts +67 -0
- package/dist/commands/skill/test/configure-schema.d.ts.map +1 -0
- package/dist/commands/skill/test/configure-schema.js +27 -0
- package/dist/commands/skill/test/configure-schema.js.map +1 -0
- package/dist/commands/skill/test/configure.d.ts +12 -5
- package/dist/commands/skill/test/configure.d.ts.map +1 -1
- package/dist/commands/skill/test/configure.js +101 -31
- package/dist/commands/skill/test/configure.js.map +1 -1
- package/dist/commands/skill/test/run-schema.d.ts +107 -0
- package/dist/commands/skill/test/run-schema.d.ts.map +1 -0
- package/dist/commands/skill/test/run-schema.js +36 -0
- package/dist/commands/skill/test/run-schema.js.map +1 -0
- package/dist/commands/skill/test/run.d.ts +3 -2
- package/dist/commands/skill/test/run.d.ts.map +1 -1
- package/dist/commands/skill/test/run.js +316 -155
- package/dist/commands/skill/test/run.js.map +1 -1
- package/dist/commands/skills/build-schema.d.ts +199 -0
- package/dist/commands/skills/build-schema.d.ts.map +1 -0
- package/dist/commands/skills/build-schema.js +55 -0
- package/dist/commands/skills/build-schema.js.map +1 -0
- package/dist/commands/skills/build.d.ts +95 -298
- package/dist/commands/skills/build.d.ts.map +1 -1
- package/dist/commands/skills/build.js +415 -818
- package/dist/commands/skills/build.js.map +1 -1
- package/dist/commands/skills/command-helpers.d.ts +5 -11
- package/dist/commands/skills/command-helpers.d.ts.map +1 -1
- package/dist/commands/skills/command-helpers.js +7 -17
- package/dist/commands/skills/command-helpers.js.map +1 -1
- package/dist/commands/skills/index.js +12 -6
- package/dist/commands/skills/index.js.map +1 -1
- package/dist/commands/skills/install-schema.d.ts +153 -0
- package/dist/commands/skills/install-schema.d.ts.map +1 -0
- package/dist/commands/skills/install-schema.js +44 -0
- package/dist/commands/skills/install-schema.js.map +1 -0
- package/dist/commands/skills/install.d.ts +76 -8
- package/dist/commands/skills/install.d.ts.map +1 -1
- package/dist/commands/skills/install.js +230 -194
- package/dist/commands/skills/install.js.map +1 -1
- package/dist/commands/skills/list-schema.d.ts +145 -0
- package/dist/commands/skills/list-schema.d.ts.map +1 -0
- package/dist/commands/skills/list-schema.js +37 -0
- package/dist/commands/skills/list-schema.js.map +1 -0
- package/dist/commands/skills/list.d.ts +39 -8
- package/dist/commands/skills/list.d.ts.map +1 -1
- package/dist/commands/skills/list.js +110 -122
- package/dist/commands/skills/list.js.map +1 -1
- package/dist/commands/skills/package-schema.d.ts +98 -0
- package/dist/commands/skills/package-schema.d.ts.map +1 -0
- package/dist/commands/skills/package-schema.js +32 -0
- package/dist/commands/skills/package-schema.js.map +1 -0
- package/dist/commands/skills/package.d.ts +85 -14
- package/dist/commands/skills/package.d.ts.map +1 -1
- package/dist/commands/skills/package.js +288 -207
- package/dist/commands/skills/package.js.map +1 -1
- package/dist/commands/skills/scope-guard.d.ts +27 -20
- package/dist/commands/skills/scope-guard.d.ts.map +1 -1
- package/dist/commands/skills/scope-guard.js +43 -28
- package/dist/commands/skills/scope-guard.js.map +1 -1
- package/dist/commands/skills/skill-discovery.d.ts +1 -1
- package/dist/commands/skills/skill-discovery.d.ts.map +1 -1
- package/dist/commands/skills/skill-discovery.js +40 -19
- package/dist/commands/skills/skill-discovery.js.map +1 -1
- package/dist/commands/skills/source-resolvers.d.ts +58 -8
- package/dist/commands/skills/source-resolvers.d.ts.map +1 -1
- package/dist/commands/skills/source-resolvers.js +113 -38
- package/dist/commands/skills/source-resolvers.js.map +1 -1
- package/dist/commands/skills/validate-command.d.ts.map +1 -1
- package/dist/commands/skills/validate-command.js +31 -51
- package/dist/commands/skills/validate-command.js.map +1 -1
- package/dist/commands/skills/validate-schema.d.ts +199 -0
- package/dist/commands/skills/validate-schema.d.ts.map +1 -0
- package/dist/commands/skills/validate-schema.js +44 -0
- package/dist/commands/skills/validate-schema.js.map +1 -0
- package/dist/commands/skills/validate.d.ts +100 -136
- package/dist/commands/skills/validate.d.ts.map +1 -1
- package/dist/commands/skills/validate.js +257 -343
- package/dist/commands/skills/validate.js.map +1 -1
- package/dist/commands/validate.d.ts +17 -5
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +139 -94
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/verify.d.ts +121 -110
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +230 -294
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/report-schemas.d.ts +12398 -35
- package/dist/report-schemas.d.ts.map +1 -1
- package/dist/report-schemas.js +624 -66
- package/dist/report-schemas.js.map +1 -1
- package/dist/skill-resolution/packaging-config.js +2 -2
- package/dist/skill-resolution/packaging-config.js.map +1 -1
- package/dist/skill-resolution/resolve-skill-reference.d.ts.map +1 -1
- package/dist/skill-resolution/resolve-skill-reference.js +20 -13
- package/dist/skill-resolution/resolve-skill-reference.js.map +1 -1
- package/dist/utils/agent-discovery.d.ts +34 -1
- package/dist/utils/agent-discovery.d.ts.map +1 -1
- package/dist/utils/agent-discovery.js +80 -38
- package/dist/utils/agent-discovery.js.map +1 -1
- package/dist/utils/claude-context-lens.d.ts +13 -6
- package/dist/utils/claude-context-lens.d.ts.map +1 -1
- package/dist/utils/claude-context-lens.js +11 -12
- package/dist/utils/claude-context-lens.js.map +1 -1
- package/dist/utils/command-error-codes.d.ts +12 -0
- package/dist/utils/command-error-codes.d.ts.map +1 -0
- package/dist/utils/command-error-codes.js +12 -0
- package/dist/utils/command-error-codes.js.map +1 -0
- package/dist/utils/command-refusal.d.ts +58 -0
- package/dist/utils/command-refusal.d.ts.map +1 -0
- package/dist/utils/command-refusal.js +170 -0
- package/dist/utils/command-refusal.js.map +1 -0
- package/dist/utils/commander-ending.d.ts +40 -0
- package/dist/utils/commander-ending.d.ts.map +1 -0
- package/dist/utils/commander-ending.js +42 -0
- package/dist/utils/commander-ending.js.map +1 -0
- package/dist/utils/config-loader.d.ts +13 -8
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +84 -45
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/corpus-target.d.ts +1 -1
- package/dist/utils/corpus-target.d.ts.map +1 -1
- package/dist/utils/corpus-target.js +44 -5
- package/dist/utils/corpus-target.js.map +1 -1
- package/dist/utils/debug-diagnostics.d.ts +18 -0
- package/dist/utils/debug-diagnostics.d.ts.map +1 -0
- package/dist/utils/debug-diagnostics.js +23 -0
- package/dist/utils/debug-diagnostics.js.map +1 -0
- package/dist/utils/document-writer.d.ts +191 -0
- package/dist/utils/document-writer.d.ts.map +1 -0
- package/dist/utils/document-writer.js +319 -0
- package/dist/utils/document-writer.js.map +1 -0
- package/dist/utils/help-loader.d.ts +2 -2
- package/dist/utils/help-loader.js +2 -2
- package/dist/utils/install-plan.d.ts +99 -0
- package/dist/utils/install-plan.d.ts.map +1 -0
- package/dist/utils/install-plan.js +146 -0
- package/dist/utils/install-plan.js.map +1 -0
- package/dist/utils/issue-anchor.d.ts +1 -1
- package/dist/utils/issue-anchor.d.ts.map +1 -1
- package/dist/utils/issue-anchor.js.map +1 -1
- package/dist/utils/issue-rendering.d.ts +8 -3
- package/dist/utils/issue-rendering.d.ts.map +1 -1
- package/dist/utils/issue-rendering.js +4 -0
- package/dist/utils/issue-rendering.js.map +1 -1
- package/dist/utils/lens-population.d.ts +20 -0
- package/dist/utils/lens-population.d.ts.map +1 -0
- package/dist/utils/lens-population.js +15 -0
- package/dist/utils/lens-population.js.map +1 -0
- package/dist/utils/marketplace-io.d.ts +63 -0
- package/dist/utils/marketplace-io.d.ts.map +1 -0
- package/dist/utils/marketplace-io.js +63 -0
- package/dist/utils/marketplace-io.js.map +1 -0
- package/dist/utils/operator-notices.d.ts +97 -0
- package/dist/utils/operator-notices.d.ts.map +1 -0
- package/dist/utils/operator-notices.js +115 -0
- package/dist/utils/operator-notices.js.map +1 -0
- package/dist/utils/optional-backend.d.ts +18 -15
- package/dist/utils/optional-backend.d.ts.map +1 -1
- package/dist/utils/optional-backend.js +22 -33
- package/dist/utils/optional-backend.js.map +1 -1
- package/dist/utils/output.d.ts +5 -43
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +8 -63
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/package-json.d.ts +3 -4
- package/dist/utils/package-json.d.ts.map +1 -1
- package/dist/utils/package-json.js +8 -8
- package/dist/utils/package-json.js.map +1 -1
- package/dist/utils/population-wiring.d.ts +31 -38
- package/dist/utils/population-wiring.d.ts.map +1 -1
- package/dist/utils/population-wiring.js +38 -32
- package/dist/utils/population-wiring.js.map +1 -1
- package/dist/utils/project-root-policy.d.ts +74 -1
- package/dist/utils/project-root-policy.d.ts.map +1 -1
- package/dist/utils/project-root-policy.js +146 -8
- package/dist/utils/project-root-policy.js.map +1 -1
- package/dist/utils/projection-lenses.d.ts +25 -7
- package/dist/utils/projection-lenses.d.ts.map +1 -1
- package/dist/utils/projection-lenses.js +20 -6
- package/dist/utils/projection-lenses.js.map +1 -1
- package/dist/utils/projection-query.d.ts +18 -11
- package/dist/utils/projection-query.d.ts.map +1 -1
- package/dist/utils/projection-query.js +47 -28
- package/dist/utils/projection-query.js.map +1 -1
- package/dist/utils/projection-store.d.ts +2 -2
- package/dist/utils/projection-store.d.ts.map +1 -1
- package/dist/utils/projection-store.js +74 -45
- package/dist/utils/projection-store.js.map +1 -1
- package/dist/utils/rag-database.d.ts +61 -0
- package/dist/utils/rag-database.d.ts.map +1 -0
- package/dist/utils/rag-database.js +178 -0
- package/dist/utils/rag-database.js.map +1 -0
- package/dist/utils/relation-limits.d.ts +7 -2
- package/dist/utils/relation-limits.d.ts.map +1 -1
- package/dist/utils/relation-limits.js +6 -1
- package/dist/utils/relation-limits.js.map +1 -1
- package/dist/utils/relativize-paths.d.ts +23 -0
- package/dist/utils/relativize-paths.d.ts.map +1 -1
- package/dist/utils/relativize-paths.js +32 -1
- package/dist/utils/relativize-paths.js.map +1 -1
- package/dist/utils/resource-loader.d.ts +78 -32
- package/dist/utils/resource-loader.d.ts.map +1 -1
- package/dist/utils/resource-loader.js +134 -66
- package/dist/utils/resource-loader.js.map +1 -1
- package/dist/utils/run-integrity.d.ts +64 -31
- package/dist/utils/run-integrity.d.ts.map +1 -1
- package/dist/utils/run-integrity.js +76 -35
- package/dist/utils/run-integrity.js.map +1 -1
- package/dist/utils/scope-locations.d.ts +7 -5
- package/dist/utils/scope-locations.d.ts.map +1 -1
- package/dist/utils/scope-locations.js +37 -12
- package/dist/utils/scope-locations.js.map +1 -1
- package/dist/utils/staging-dir.d.ts +7 -0
- package/dist/utils/staging-dir.d.ts.map +1 -0
- package/dist/utils/staging-dir.js +12 -0
- package/dist/utils/staging-dir.js.map +1 -0
- package/dist/utils/url-redact.d.ts +9 -0
- package/dist/utils/url-redact.d.ts.map +1 -1
- package/dist/utils/url-redact.js +13 -0
- package/dist/utils/url-redact.js.map +1 -1
- package/dist/utils/user-context-scanner.d.ts +3 -2
- package/dist/utils/user-context-scanner.d.ts.map +1 -1
- package/dist/utils/user-context-scanner.js +24 -4
- package/dist/utils/user-context-scanner.js.map +1 -1
- package/dist/utils/validate-help-files.d.ts.map +1 -1
- package/dist/utils/validate-help-files.js +8 -14
- package/dist/utils/validate-help-files.js.map +1 -1
- package/dist/utils/vat-bin-path.d.ts.map +1 -1
- package/dist/utils/vat-bin-path.js +3 -3
- package/dist/utils/vat-bin-path.js.map +1 -1
- package/dist/utils/verdict-helpers.d.ts.map +1 -1
- package/dist/utils/verdict-helpers.js +5 -5
- package/dist/utils/verdict-helpers.js.map +1 -1
- package/docs/agent.md +347 -2
- package/docs/audit.md +312 -89
- package/docs/doctor.md +65 -19
- package/docs/index.md +571 -20
- package/docs/mcp.md +64 -12
- package/docs/rag.md +176 -48
- package/docs/resources.md +257 -71
- package/docs/skill-test.md +148 -19
- package/docs/skills.md +459 -174
- package/package.json +17 -20
- package/schemas/agent-build.json +268 -0
- package/schemas/agent-import.json +252 -0
- package/schemas/agent-install.json +260 -0
- package/schemas/agent-installed.json +287 -0
- package/schemas/agent-list.json +279 -0
- package/schemas/agent-uninstall.json +260 -0
- package/schemas/agent-validate.json +279 -0
- package/schemas/ard-emit.json +228 -107
- package/schemas/audit-settings.json +472 -0
- package/schemas/audit.json +635 -0
- package/schemas/cache-clear.json +273 -0
- package/schemas/claude-marketplace-publish.json +286 -0
- package/schemas/claude-marketplace-validate.json +352 -0
- package/schemas/claude-org-not-implemented.json +239 -0
- package/schemas/claude-plugin-build.json +446 -0
- package/schemas/claude-plugin-install.json +291 -0
- package/schemas/claude-plugin-list.json +326 -0
- package/schemas/claude-plugin-uninstall.json +272 -0
- package/schemas/corpus-audit.json +635 -0
- package/schemas/corpus-scan.json +293 -0
- package/schemas/doctor.json +299 -0
- package/schemas/inventory.json +982 -0
- package/schemas/mcp-list-collections.json +268 -0
- package/schemas/okf-validate.json +224 -106
- package/schemas/orchestrator.json +299 -0
- package/schemas/rag-clear.json +253 -0
- package/schemas/rag-index.json +273 -0
- package/schemas/rag-query.json +365 -0
- package/schemas/rag-stats.json +269 -0
- package/schemas/resources-check.json +280 -118
- package/schemas/resources-query.json +333 -0
- package/schemas/resources-scan.json +321 -0
- package/schemas/resources-validate.json +332 -0
- package/schemas/skill-review.json +224 -106
- package/schemas/skill-test-configure.json +256 -0
- package/schemas/skill-test-run.json +296 -0
- package/schemas/skills-build.json +325 -0
- package/schemas/skills-install.json +287 -0
- package/schemas/skills-list.json +283 -0
- package/schemas/skills-package.json +270 -0
- package/schemas/skills-validate.json +285 -0
- package/dist/commands/skills/shared.d.ts +0 -29
- package/dist/commands/skills/shared.d.ts.map +0 -1
- package/dist/commands/skills/shared.js +0 -33
- package/dist/commands/skills/shared.js.map +0 -1
- package/dist/utils/command-error.d.ts +0 -189
- package/dist/utils/command-error.d.ts.map +0 -1
- package/dist/utils/command-error.js +0 -230
- package/dist/utils/command-error.js.map +0 -1
package/dist/commands/audit.js
CHANGED
|
@@ -3,32 +3,33 @@
|
|
|
3
3
|
* Top-level command: vat audit [path]
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from 'node:fs';
|
|
6
|
-
import { existsSync as fsExistsSync } from 'node:fs';
|
|
7
6
|
import { basename } from 'node:path';
|
|
8
|
-
import { conventionalSuiteProbe, crawlAndResolveRegistry, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, resetPackagingRegistryCache, detectPresentButUndeclared, detectReferenceTargetMissing, detectResourceFormat, enumerateSurfaces, materializeIssue, validate, validateMarketplace, validateSkill, validateSkillForPackaging, } from '@vibe-agent-toolkit/agent-skills';
|
|
7
|
+
import { conventionalSuiteProbe, crawlAndResolveRegistry, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, resetPackagingRegistryCache, detectPresentButUndeclared, detectReferenceTargetMissing, describeIssues, detectResourceFormat, enumerateSurfaces, materializeIssue, validate, validateMarketplace, validateSkill, validateSkillForPackaging, } from '@vibe-agent-toolkit/agent-skills';
|
|
9
8
|
import { analyzeCompatibility, checkSettingsCompatibility, detectSkillClaudePluginNameMismatch, crawlSkillLinkRegistry, extractClaudeMarketplaceInventory, extractClaudePluginInventory, getClaudeUserPaths, readEffectiveSettings, validatePlugin, } from '@vibe-agent-toolkit/claude-marketplace';
|
|
10
9
|
import { detectFormat } from '@vibe-agent-toolkit/discovery';
|
|
11
10
|
import { listingRefusalRemedy } from '@vibe-agent-toolkit/resources';
|
|
12
|
-
import {
|
|
13
|
-
import { findProjectRoot,
|
|
11
|
+
import { buildReport, countBySeverity, exitCodeForReport, summarizeIssues, toFindings, withAddedFindings, } from '@vibe-agent-toolkit/schema';
|
|
12
|
+
import { everywhere, findProjectRoot, followedKind, followedKindSync, forEachInOrder, fsFaultOf, isPathAbsentError, issueLocation, mapInOrder, pathPresent, relativeEscapesRoot, resetProjectRootCaches, safePath, toForwardSlash, } from '@vibe-agent-toolkit/utils';
|
|
14
13
|
import { DirectoryListingRefusedError } from '@vibe-agent-toolkit/utils/crawl';
|
|
15
14
|
import { gitFindRoot, isGitUrl, parseGitUrl, } from '@vibe-agent-toolkit/utils/git';
|
|
16
15
|
import { Command } from 'commander';
|
|
17
16
|
import { resetSkillDiscoveryCache, resolveProjectDeclaredEvalSuites, resolveSkillPackagingConfig, stripValidationAllowForDisplay, } from '../skill-resolution/packaging-config.js';
|
|
18
|
-
import {
|
|
17
|
+
import { CommandRefusalError, errorMessageOf, refusalCodeOf } from '../utils/command-refusal.js';
|
|
19
18
|
import { ConfigLoadError, loadConfig, resetLoadedConfigCache, } from '../utils/config-loader.js';
|
|
20
|
-
import {
|
|
19
|
+
import { endWithRefusal, leftoverIssueOf, NOTHING_FINISHED, writeDocument } from '../utils/document-writer.js';
|
|
20
|
+
import { countCollapsedFindings, formatCollapsedFindingsHint, formatIssueLines, formatSeverityBreakdown, issuesToRenderAtVerbosity, } from '../utils/issue-rendering.js';
|
|
21
21
|
import { resolveIssueSeverity } from '../utils/issue-severity.js';
|
|
22
22
|
import { createLogger } from '../utils/logger.js';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
23
|
+
import { classifyInputFault, readInputFile, unlistableDirectoryRefusal } from '../utils/project-root-policy.js';
|
|
24
|
+
import { relativizePath } from '../utils/relativize-paths.js';
|
|
25
|
+
import { RUN_INTEGRITY_CODE } from '../utils/run-integrity.js';
|
|
26
26
|
import { mergeSkillPackagingConfig } from '../utils/skill-packaging-config.js';
|
|
27
27
|
import { renderSkillQualityFooter } from '../utils/skill-quality-footer.js';
|
|
28
28
|
import { computeConfigVerdicts } from '../utils/verdict-helpers.js';
|
|
29
|
+
import { compatLaneIssues } from './audit/compat-lane-findings.js';
|
|
29
30
|
import { crawlOwnsSubtree, distributedTreeFindings, getOrCreateGitTracker, gitTrackerForProjectRoot, isWithin, resetGitTrackerCache, } from './audit/distributed-tree.js';
|
|
30
31
|
import { withClonedRepo } from './audit/git-url-clone.js';
|
|
31
|
-
import { buildHierarchicalOutput } from './audit/hierarchical-output.js';
|
|
32
|
+
import { addMisconfigurationIssues, buildHierarchicalOutput } from './audit/hierarchical-output.js';
|
|
32
33
|
import { renderProvenanceHeader, rewritePathsInResults, } from './audit/provenance.js';
|
|
33
34
|
import { enumerateAuditPopulation, resolveProjectExcludes, VAT_CONFIG_FILENAME, } from './audit/scan-population.js';
|
|
34
35
|
import { createAuditSettingsCommand } from './audit-settings.js';
|
|
@@ -55,12 +56,13 @@ const RESOURCE_TYPE_CLAUDE_PLUGIN = 'claude-plugin';
|
|
|
55
56
|
*/
|
|
56
57
|
async function buildVATProjectContext(scanRoot, logger, locationRoot) {
|
|
57
58
|
const configPath = safePath.join(scanRoot, VAT_CONFIG_FILENAME);
|
|
58
|
-
|
|
59
|
+
// A probe the OS refuses is the config's source fault, never "no config here".
|
|
60
|
+
if (!pathPresent(configPath, { follow: scanRoot }, everywhere('source'), 'probe')) {
|
|
59
61
|
return null;
|
|
60
62
|
}
|
|
61
63
|
let config;
|
|
62
64
|
try {
|
|
63
|
-
config = loadConfig(scanRoot);
|
|
65
|
+
config = loadConfig(scanRoot, 'source');
|
|
64
66
|
}
|
|
65
67
|
catch (error) {
|
|
66
68
|
logger.debug(`Config-aware audit: skipping invalid config in ${scanRoot}: ${String(error)}`);
|
|
@@ -96,23 +98,17 @@ async function buildVATProjectContext(scanRoot, logger, locationRoot) {
|
|
|
96
98
|
}
|
|
97
99
|
return { skillConfigs };
|
|
98
100
|
}
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* The one-line human summary of a severity distribution.
|
|
109
|
-
*
|
|
110
|
-
* Every result that carries findings renders its counts the same way, so a reader
|
|
111
|
-
* comparing two entries is comparing the same sentence.
|
|
112
|
-
*/
|
|
113
|
-
function formatCountsSummary(counts) {
|
|
114
|
-
return `${counts.errors} errors, ${counts.warnings} warnings, ${counts.info} info`;
|
|
101
|
+
/** A file carries an error-severity finding — the `filesWithErrors` bucket. */
|
|
102
|
+
function hasErrors(result) {
|
|
103
|
+
return countBySeverity(result.issues).errors > 0;
|
|
104
|
+
}
|
|
105
|
+
/** A file's worst actionable finding is a warning — the `filesWithWarnings` bucket. */
|
|
106
|
+
function hasOnlyWarnings(result) {
|
|
107
|
+
const { errors, warnings } = countBySeverity(result.issues);
|
|
108
|
+
return errors === 0 && warnings > 0;
|
|
115
109
|
}
|
|
110
|
+
/** `vat audit` has no `--strict`: warnings never move its exit code. */
|
|
111
|
+
const AUDIT_GATE = { strict: false };
|
|
116
112
|
/**
|
|
117
113
|
* Append findings to a result and re-derive everything that describes them.
|
|
118
114
|
*
|
|
@@ -124,17 +120,25 @@ function formatCountsSummary(counts) {
|
|
|
124
120
|
*
|
|
125
121
|
* Mutates in place, because the audit pipeline hands these results around by
|
|
126
122
|
* reference and there is no single place a rebuilt copy could be swapped in.
|
|
123
|
+
* The sentence comes from the same `describeIssues` the producer used, so the
|
|
124
|
+
* re-derived one is exactly what the producer says for the grown list — never a
|
|
125
|
+
* second wording, and never a stale "Valid plugin" beside a warning.
|
|
127
126
|
*/
|
|
128
127
|
function appendIssues(result, issues) {
|
|
129
128
|
if (issues.length === 0) {
|
|
130
129
|
return;
|
|
131
130
|
}
|
|
132
131
|
result.issues.push(...issues);
|
|
133
|
-
|
|
134
|
-
result.status = calculateValidationStatus(result.issues);
|
|
135
|
-
result.issueCounts = counts;
|
|
136
|
-
result.summary = formatCountsSummary(counts);
|
|
132
|
+
Object.assign(result, describeIssues(result.issues, result.type));
|
|
137
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Convert PackagingValidationResult to ValidationResult for consistent audit output.
|
|
136
|
+
* In audit mode, we merge allErrors (which includes both errors and warnings after
|
|
137
|
+
* severity resolution but WITHOUT allow suppression) into the standard issues array.
|
|
138
|
+
*
|
|
139
|
+
* Compat verdicts (COMPAT_TARGET_*) are computed from the result's observations
|
|
140
|
+
* and the config-level targets, then merged into the issue list.
|
|
141
|
+
*/
|
|
138
142
|
function packagingResultToValidationResult(skillPath, result, configTargets, locationRoot) {
|
|
139
143
|
// allErrors contains all emitted issues (errors + warnings) after severity resolution
|
|
140
144
|
// but without allow suppression — exactly what audit wants. Verdicts are
|
|
@@ -143,14 +147,11 @@ function packagingResultToValidationResult(skillPath, result, configTargets, loc
|
|
|
143
147
|
const issues = verdictIssues.length > 0
|
|
144
148
|
? [...result.allErrors, ...verdictIssues]
|
|
145
149
|
: result.allErrors;
|
|
146
|
-
const issueCounts = countBySeverity(issues);
|
|
147
150
|
const out = {
|
|
148
151
|
path: skillPath,
|
|
149
152
|
type: RESOURCE_TYPE_AGENT_SKILL,
|
|
150
|
-
|
|
151
|
-
summary: formatCountsSummary(issueCounts),
|
|
153
|
+
...describeIssues(issues, RESOURCE_TYPE_AGENT_SKILL),
|
|
152
154
|
issues,
|
|
153
|
-
issueCounts,
|
|
154
155
|
metadata: {
|
|
155
156
|
lineCount: result.metadata.skillLines,
|
|
156
157
|
name: result.skillName,
|
|
@@ -196,7 +197,7 @@ function packagingResultToValidationResult(skillPath, result, configTargets, loc
|
|
|
196
197
|
*
|
|
197
198
|
* ⚠️ The filesystem question IS asked, and the answer changes what the operator
|
|
198
199
|
* is told. `config-loader.ts` preserves `cause` specifically so callers can ask
|
|
199
|
-
* `
|
|
200
|
+
* `fsFaultOf` and "decide whether to degrade or abort"; catching
|
|
200
201
|
* `ConfigLoadError` unconditionally never asked at all, so a `chmod 000` config
|
|
201
202
|
* and a typo produced the same sentence — and a permissions problem is not a
|
|
202
203
|
* broken config.
|
|
@@ -317,7 +318,7 @@ function recordUnloadableConfig(err, logger, locationRoot) {
|
|
|
317
318
|
// different actions from the operator: `chmod`/ownership on one side, an edit
|
|
318
319
|
// to the file on the other. Collapsing them into one sentence was the whole
|
|
319
320
|
// cost of never asking.
|
|
320
|
-
const why =
|
|
321
|
+
const why = fsFaultOf(err) === undefined ? 'unloadable' : 'unreadable';
|
|
321
322
|
logger.warn(`Ignoring ${why} config at ${configPath}; skills it governs are validated`
|
|
322
323
|
+ ` config-free: ${err.message}`);
|
|
323
324
|
}
|
|
@@ -340,7 +341,7 @@ function recordUnloadableConfig(err, logger, locationRoot) {
|
|
|
340
341
|
function degradingDiscovery(configRoot, logger, locationRoot) {
|
|
341
342
|
return {
|
|
342
343
|
degrade: (refusal) => {
|
|
343
|
-
recordRefusedDiscovery(new DirectoryListingRefusedError(refusal, { root: configRoot, remedy: SKILLS_INCLUDE_REMEDY }), configRoot, logger, locationRoot);
|
|
344
|
+
recordRefusedDiscovery(new DirectoryListingRefusedError(refusal, { root: configRoot, remedy: SKILLS_INCLUDE_REMEDY, side: 'source' }), configRoot, logger, locationRoot);
|
|
344
345
|
},
|
|
345
346
|
};
|
|
346
347
|
}
|
|
@@ -372,7 +373,7 @@ function degradingDiscovery(configRoot, logger, locationRoot) {
|
|
|
372
373
|
function degradingRegistry(projectRoot, logger, locationRoot) {
|
|
373
374
|
return {
|
|
374
375
|
degrade: (refusal) => {
|
|
375
|
-
const err = new DirectoryListingRefusedError(refusal, { root: projectRoot, remedy: listingRefusalRemedy(projectRoot) });
|
|
376
|
+
const err = new DirectoryListingRefusedError(refusal, { root: projectRoot, remedy: listingRefusalRemedy(projectRoot), side: 'source' });
|
|
376
377
|
recordRefusedListing(err, logger, locationRoot, () => `The link graph under ${projectRoot} skipped an unreadable directory; every document beneath it`
|
|
377
378
|
+ ` is missing from this audit's link and reference checks: ${err.message}`);
|
|
378
379
|
},
|
|
@@ -469,8 +470,10 @@ async function validateSingleSkill(skillPath, options, logger, locationRoot, cra
|
|
|
469
470
|
// makes when this registry does not cover the skill: one ruling, both crawls.
|
|
470
471
|
const unreadable = degradingRegistry(projectRoot, logger, locationRoot);
|
|
471
472
|
const sharedCtx = {
|
|
472
|
-
registry: await crawlAndResolveRegistry(projectRoot, { unreadable }),
|
|
473
|
+
registry: await crawlAndResolveRegistry(projectRoot, { outputs: [], unreadable }),
|
|
473
474
|
unreadable,
|
|
475
|
+
// An audit only reads the trees it scans.
|
|
476
|
+
outputs: [],
|
|
474
477
|
locationRoot,
|
|
475
478
|
projectSkills: await resolveProjectDeclaredEvalSuites(skillPath, degradingDiscovery(projectRoot, logger, locationRoot)),
|
|
476
479
|
// The RUN's probe, not this call's — see {@link runSuiteProbe}. This lane
|
|
@@ -486,7 +489,8 @@ async function validateSingleSkill(skillPath, options, logger, locationRoot, cra
|
|
|
486
489
|
return configAware;
|
|
487
490
|
}
|
|
488
491
|
// Fallback: basic validation. Severity is applied by `applySeverityFilter`.
|
|
489
|
-
|
|
492
|
+
// The audited skill is the verb's input.
|
|
493
|
+
const validateOptions = { skillPath, locationRoot, validation: {}, side: 'source' };
|
|
490
494
|
if (options.warnUnreferencedFiles) {
|
|
491
495
|
validateOptions.checkUnreferencedFiles = true;
|
|
492
496
|
}
|
|
@@ -533,13 +537,13 @@ function collect(value, previous) {
|
|
|
533
537
|
* Create audit command
|
|
534
538
|
* Top-level command: vat audit [path]
|
|
535
539
|
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
* `FINDINGS` when
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
540
|
+
* Publishes the report envelope through the one writer, and ends on the code
|
|
541
|
+
* the written document derives — the rule every report verb shares: `OK` when
|
|
542
|
+
* no finding is at error severity, `FINDINGS` when one is (a run that audited
|
|
543
|
+
* zero files carries the writer's `RESOURCE_CHECK_BROKEN`), `ERROR` only when
|
|
544
|
+
* the audit did not finish (`status: error`, with the refusal in `error.code`).
|
|
545
|
+
* Warnings never move the exit code — audit has no `--strict`;
|
|
546
|
+
* `validation.severity` is the dial that decides what counts.
|
|
543
547
|
*/
|
|
544
548
|
export function createAuditCommand() {
|
|
545
549
|
const audit = new Command('audit');
|
|
@@ -607,12 +611,19 @@ Description:
|
|
|
607
611
|
(See packages/cli/docs/audit.md for details.)
|
|
608
612
|
|
|
609
613
|
Output:
|
|
610
|
-
The
|
|
611
|
-
|
|
614
|
+
The report envelope every report verb publishes (YAML on stdout):
|
|
615
|
+
- status: ok (no findings) | findings (at least one) | error (did not finish)
|
|
616
|
+
- examined: files read; summary: findings by severity; gate: { strict: false }
|
|
617
|
+
- findings: every finding, each with the file to open as 'location'
|
|
618
|
+
- data.root: the scan root every path is relative to (null for a git URL,
|
|
619
|
+
whose data.provenance names the source instead)
|
|
620
|
+
- data.counts: filesPassed / filesWithWarnings / filesWithErrors /
|
|
621
|
+
pathsUnreadable; data.files: one row per file (status, summary,
|
|
622
|
+
compatibility, settings); data.hierarchical: the --user grouping
|
|
623
|
+
- error: { code, message } when status is error
|
|
612
624
|
|
|
613
|
-
A run that audited ZERO files is
|
|
614
|
-
non-overridable RESOURCE_CHECK_BROKEN
|
|
615
|
-
about the run, so it is not a files[] row), and exit 1.
|
|
625
|
+
A run that audited ZERO files is not a pass: the report carries one
|
|
626
|
+
non-overridable RESOURCE_CHECK_BROKEN finding and ends on exit 1.
|
|
616
627
|
|
|
617
628
|
Validation Behavior:
|
|
618
629
|
Audit surfaces all validation issues for inspection.
|
|
@@ -620,9 +631,8 @@ Validation Behavior:
|
|
|
620
631
|
- NEVER applies validation.allow (allowed codes are always shown)
|
|
621
632
|
- Respects validation.severity: a code set to 'ignore' is hidden; warnings
|
|
622
633
|
and errors are both reported, each at its configured severity
|
|
623
|
-
- ALWAYS exits 0 for validation results (never gates on errors)
|
|
624
634
|
|
|
625
|
-
For gated validation
|
|
635
|
+
For gated validation that honours validation.allow, use: vat skills validate
|
|
626
636
|
For the full list of codes and severity defaults, see: docs/validation-codes.md
|
|
627
637
|
|
|
628
638
|
Default: Validates SKILL.md and all transitively linked markdown files
|
|
@@ -640,7 +650,10 @@ Validation Checks:
|
|
|
640
650
|
Warnings (should fix):
|
|
641
651
|
- Skill exceeds recommended length (>5000 lines)
|
|
642
652
|
- With --compat: a declared target cannot or may not run the skill
|
|
643
|
-
(COMPAT_TARGET_INCOMPATIBLE, COMPAT_TARGET_NEEDS_REVIEW)
|
|
653
|
+
(COMPAT_TARGET_INCOMPATIBLE, COMPAT_TARGET_NEEDS_REVIEW); a plugin or a
|
|
654
|
+
path the analysis could not look at (COMPAT_NOT_CHECKED)
|
|
655
|
+
- With --compat --settings: something the plugin declares that the settings
|
|
656
|
+
block (SETTINGS_POLICY_CONFLICT)
|
|
644
657
|
- Unreferenced files detected (with --warn-unreferenced-files)
|
|
645
658
|
|
|
646
659
|
Info (observations):
|
|
@@ -679,20 +692,23 @@ Config-Aware Validation:
|
|
|
679
692
|
skills.config.<name>.validation... that one skill
|
|
680
693
|
|
|
681
694
|
Exit Codes:
|
|
682
|
-
0 - The audit
|
|
695
|
+
0 - The audit finished and no finding is at error severity (warnings and
|
|
683
696
|
informational findings are in the report, not the exit code).
|
|
684
|
-
1 - The audit
|
|
685
|
-
|
|
686
|
-
the scan could not read, or a governing config that cannot be
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
a
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
that
|
|
695
|
-
|
|
697
|
+
1 - The audit finished with at least one error-severity finding
|
|
698
|
+
('status: findings'), including zero files audited. A path inside the
|
|
699
|
+
tree the scan could not read, or a governing config that cannot be
|
|
700
|
+
loaded, is SCAN_PATH_UNREADABLE (warning): the run is degraded, not
|
|
701
|
+
failed, and the refused path is counted in data.counts.pathsUnreadable,
|
|
702
|
+
never in 'examined'.
|
|
703
|
+
2 - The audit did not finish ('status: error', the reason in error.code):
|
|
704
|
+
USAGE_INVALID for a path that does not exist, a file no audit lane
|
|
705
|
+
recognises, a git URL that does not parse, --user with no Claude
|
|
706
|
+
config dir, --settings without --compat or together with --user, or a
|
|
707
|
+
--settings file that does not exist; INPUT_UNREADABLE for a root
|
|
708
|
+
directory the OS will not list, a git URL that would not clone, or a
|
|
709
|
+
settings file (named or auto-discovered) the OS refuses, that does not
|
|
710
|
+
parse, or that fails the settings schema; INTERNAL_ERROR for a defect
|
|
711
|
+
in VAT.
|
|
696
712
|
|
|
697
713
|
Examples:
|
|
698
714
|
$ vat audit ./plugins/ # Audit recursively (default)
|
|
@@ -739,23 +755,22 @@ export function userScanTargets(candidates, recursive) {
|
|
|
739
755
|
}
|
|
740
756
|
/**
|
|
741
757
|
* Handle --user audit: scans ~/.claude/plugins, ~/.claude/skills, ~/.claude/marketplaces
|
|
742
|
-
* and
|
|
758
|
+
* and publishes the report with its `data.hierarchical` view. Calls process.exit() when done.
|
|
743
759
|
*/
|
|
744
760
|
async function auditUserDirectories(recursive, options, startTime, logger) {
|
|
745
761
|
const { claudeDir, pluginsDir, skillsDir, marketplacesDir } = getClaudeUserPaths();
|
|
746
762
|
// --user scans three sibling directories; they share ONE enclosing Claude
|
|
747
763
|
// config dir, so that is the run's single stated root.
|
|
748
764
|
const scanRoot = safePath.resolve(claudeDir);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
const
|
|
765
|
+
// Each install root is the operator's own configuration (`CLAUDE_CONFIG_DIR`/`HOME`), so it is
|
|
766
|
+
// its own `within`; a probe the OS refuses is that root's source fault, never "not installed".
|
|
767
|
+
const userRootPresent = (dir) => pathPresent(dir, { follow: dir }, everywhere('source'), 'probe');
|
|
768
|
+
const pluginsDirExists = userRootPresent(pluginsDir);
|
|
769
|
+
const skillsDirExists = userRootPresent(skillsDir);
|
|
770
|
+
const marketplacesDirExists = userRootPresent(marketplacesDir);
|
|
752
771
|
if (!pluginsDirExists && !skillsDirExists && !marketplacesDirExists) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
logger.error(` Skills: ${skillsDir}`);
|
|
756
|
-
logger.error(` Marketplaces: ${marketplacesDir}`);
|
|
757
|
-
logger.error('Claude plugins/skills/marketplaces have not been installed yet.');
|
|
758
|
-
process.exit(ExitCode.ERROR);
|
|
772
|
+
throw new CommandRefusalError('USAGE_INVALID', `No user-level Claude directories found (plugins: ${pluginsDir}, skills: ${skillsDir}, marketplaces: ${marketplacesDir}). `
|
|
773
|
+
+ 'Claude plugins, skills and marketplaces have not been installed yet — set CLAUDE_CONFIG_DIR to the config dir to audit.');
|
|
759
774
|
}
|
|
760
775
|
const scanned = [];
|
|
761
776
|
// The roots that exist, minus any one another already covers — see
|
|
@@ -765,27 +780,36 @@ async function auditUserDirectories(recursive, options, startTime, logger) {
|
|
|
765
780
|
...(skillsDirExists ? [skillsDir] : []),
|
|
766
781
|
...(marketplacesDirExists ? [marketplacesDir] : []),
|
|
767
782
|
];
|
|
768
|
-
|
|
783
|
+
// In order: the targets share the population cache and the logger.
|
|
784
|
+
await forEachInOrder(userScanTargets(present, recursive), async (target) => {
|
|
769
785
|
logger.debug(`Auditing user-level resources at: ${target}`);
|
|
770
786
|
scanned.push(...await getValidationResults(target, recursive, options, logger, scanRoot));
|
|
771
|
-
}
|
|
787
|
+
});
|
|
772
788
|
// The `--user` report is assembled here rather than by `buildAuditReport`, so
|
|
773
789
|
// it needs its own append or the config findings would reach stderr and not the
|
|
774
|
-
// document — see the same call in `buildAuditReport`.
|
|
775
|
-
|
|
790
|
+
// document — see the same call in `buildAuditReport`. The misconfiguration
|
|
791
|
+
// findings join the RESULTS, not only the hierarchy, so the envelope counts them.
|
|
792
|
+
const results = addMisconfigurationIssues(withDegradedConfigFindings(scanned), scanRoot);
|
|
776
793
|
// Run compatibility analysis if --compat flag is set
|
|
777
794
|
const compatMap = options.compat
|
|
778
|
-
? await runCompatAnalysis(results, logger, scanRoot) // --settings
|
|
795
|
+
? await runCompatAnalysis(results, logger, scanRoot) // --settings is refused under --user
|
|
779
796
|
: undefined;
|
|
780
797
|
const verbose = options.verbose ?? false;
|
|
781
798
|
const skillResults = results.filter((r) => SKILL_RESULT_TYPES.has(r.type));
|
|
782
799
|
const hierarchical = buildHierarchicalOutput(skillResults, verbose, scanRoot);
|
|
783
|
-
const
|
|
784
|
-
|
|
800
|
+
const report = buildAuditDocument(results, {
|
|
801
|
+
root: scanRoot,
|
|
802
|
+
compatMap,
|
|
803
|
+
verbose,
|
|
804
|
+
hierarchical,
|
|
805
|
+
durationMs: Date.now() - startTime,
|
|
806
|
+
});
|
|
807
|
+
const written = writeDocument('audit', report, 'yaml');
|
|
785
808
|
if (verbose) {
|
|
786
809
|
renderVerboseEvidence(results, scanRoot, logger);
|
|
787
810
|
}
|
|
788
|
-
logHierarchicalSummary(results,
|
|
811
|
+
logHierarchicalSummary({ results, written, data: report.data, root: scanRoot, verbose }, logger);
|
|
812
|
+
process.exit(exitCodeForReport(written));
|
|
789
813
|
}
|
|
790
814
|
/** Skill resource types that can have per-skill validation config. */
|
|
791
815
|
const SKILL_RESULT_TYPES = new Set([RESOURCE_TYPE_AGENT_SKILL, 'vat-agent']);
|
|
@@ -809,7 +833,8 @@ const SKILL_RESULT_TYPES = new Set([RESOURCE_TYPE_AGENT_SKILL, 'vat-agent']);
|
|
|
809
833
|
*/
|
|
810
834
|
export function deriveScanRoot(targetPath) {
|
|
811
835
|
const resolved = safePath.resolve(targetPath);
|
|
812
|
-
|
|
836
|
+
// The operator's own target: its own `within`.
|
|
837
|
+
const isDirectory = followedKindSync(resolved, resolved) === 'directory';
|
|
813
838
|
return isDirectory ? resolved : safePath.resolve(resolved, '..');
|
|
814
839
|
}
|
|
815
840
|
/**
|
|
@@ -841,15 +866,12 @@ function deriveConfigRoot(targetPath) {
|
|
|
841
866
|
* Build the recalculated status and summary after issues have been filtered.
|
|
842
867
|
*/
|
|
843
868
|
function buildFilteredResult(result, filteredIssues) {
|
|
844
|
-
const counts = countBySeverity(filteredIssues);
|
|
845
869
|
return {
|
|
846
870
|
...result,
|
|
847
|
-
|
|
848
|
-
// Spreading `result` carried the PRE-filter `issueCounts` forward, so a
|
|
871
|
+
// Spreading `result` carried the PRE-filter counts forward, so a
|
|
849
872
|
// `severity: ignore` config left the counts describing findings the report
|
|
850
873
|
// no longer contained. The counts are re-derived, never inherited.
|
|
851
|
-
|
|
852
|
-
summary: formatCountsSummary(counts),
|
|
874
|
+
...describeIssues(filteredIssues, result.type),
|
|
853
875
|
issues: filteredIssues,
|
|
854
876
|
};
|
|
855
877
|
}
|
|
@@ -970,29 +992,57 @@ function isEmptiedUnreadablePathResult(result) {
|
|
|
970
992
|
&& result.metadata === undefined;
|
|
971
993
|
}
|
|
972
994
|
/**
|
|
973
|
-
*
|
|
974
|
-
*
|
|
995
|
+
* Refuse a `--settings` the run would otherwise ignore, before any scan or clone.
|
|
996
|
+
*
|
|
997
|
+
* Every arm used to be a stderr line and exit 0: without `--compat` a warning
|
|
998
|
+
* and no settings check; under `--user` nothing at all; and a named file that
|
|
999
|
+
* is absent read as "no settings", so `--compat --settings /typo.json` printed
|
|
1000
|
+
* `findings: []` for a check that never compared anything. The sibling verb
|
|
1001
|
+
* `audit settings --file <missing>` refuses the same path.
|
|
1002
|
+
*
|
|
1003
|
+
* @throws {CommandRefusalError} `USAGE_INVALID` for a flag the run cannot honour
|
|
1004
|
+
* or a named file that is absent; `INPUT_UNREADABLE` for one the OS refuses
|
|
975
1005
|
*/
|
|
976
|
-
|
|
977
|
-
if (
|
|
978
|
-
return
|
|
1006
|
+
function refuseUnusableSettingsFlag(options) {
|
|
1007
|
+
if (options.settings === undefined || options.settings === false)
|
|
1008
|
+
return;
|
|
979
1009
|
if (!options.compat) {
|
|
980
|
-
|
|
981
|
-
|
|
1010
|
+
throw new CommandRefusalError('USAGE_INVALID', '--settings requires --compat: the settings check runs inside the compatibility analysis. Add --compat, or drop --settings.');
|
|
1011
|
+
}
|
|
1012
|
+
if (options.user) {
|
|
1013
|
+
throw new CommandRefusalError('USAGE_INVALID', '--settings is not supported with --user. Audit the plugin directory with --compat --settings instead, or drop --settings.');
|
|
982
1014
|
}
|
|
1015
|
+
if (typeof options.settings !== 'string')
|
|
1016
|
+
return;
|
|
1017
|
+
readInputFile(safePath.resolve(options.settings), { origin: 'argument', message: `Path does not exist: ${safePath.resolve(options.settings)}` });
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* The EffectiveSettings `--settings` asks the compat analysis to check against.
|
|
1021
|
+
* Called only under `--compat`; {@link refuseUnusableSettingsFlag} has already
|
|
1022
|
+
* refused every combination the run cannot honour.
|
|
1023
|
+
*
|
|
1024
|
+
* @throws {CommandRefusalError} `INPUT_UNREADABLE` when a settings file (named
|
|
1025
|
+
* or auto-discovered) the OS refuses, does not parse, or fails its schema — the check cannot run, and a warning beside
|
|
1026
|
+
* an unchecked report was how it used to pass silently
|
|
1027
|
+
*/
|
|
1028
|
+
async function resolveEffectiveSettings(options, scanPath) {
|
|
1029
|
+
if (!options.settings)
|
|
1030
|
+
return undefined;
|
|
983
1031
|
const settingsFile = typeof options.settings === 'string' ? options.settings : undefined;
|
|
984
1032
|
try {
|
|
985
1033
|
return await readEffectiveSettings({ settingsFile, projectDir: scanPath });
|
|
986
1034
|
}
|
|
987
|
-
catch (
|
|
988
|
-
|
|
989
|
-
return undefined;
|
|
1035
|
+
catch (error) {
|
|
1036
|
+
throw new CommandRefusalError('INPUT_UNREADABLE', `Claude settings could not be loaded for --settings: ${errorMessageOf(error)}`, { cause: error });
|
|
990
1037
|
}
|
|
991
1038
|
}
|
|
992
1039
|
/**
|
|
993
|
-
* Run the audit pipeline at `scanPath` and assemble the report
|
|
994
|
-
*
|
|
995
|
-
* (`root`) and every `path`/`location` beneath it is relative to that root.
|
|
1040
|
+
* Run the audit pipeline at `scanPath` and assemble the report, without
|
|
1041
|
+
* writing anything. The report states its coordinate system once
|
|
1042
|
+
* (`data.root`) and every `path`/`location` beneath it is relative to that root.
|
|
1043
|
+
*
|
|
1044
|
+
* The zero-files refusal is NOT here: the writer adds it from the registry's
|
|
1045
|
+
* denominator on the way out, as it does for every report verb.
|
|
996
1046
|
*
|
|
997
1047
|
* @internal Exported for integration testing only — not part of the public CLI API.
|
|
998
1048
|
*/
|
|
@@ -1026,7 +1076,7 @@ export async function buildAuditReport(scanPath, options, startTime, logger) {
|
|
|
1026
1076
|
// only show more than the adopter asked for, never less.
|
|
1027
1077
|
let config;
|
|
1028
1078
|
try {
|
|
1029
|
-
config = loadConfig(deriveConfigRoot(scanPath));
|
|
1079
|
+
config = loadConfig(deriveConfigRoot(scanPath), 'source');
|
|
1030
1080
|
}
|
|
1031
1081
|
catch (err) {
|
|
1032
1082
|
// `warn`, not `debug`. Falling back to no config is the safe direction — it
|
|
@@ -1040,60 +1090,95 @@ export async function buildAuditReport(scanPath, options, startTime, logger) {
|
|
|
1040
1090
|
// Apply severity filtering: hide codes whose effective severity is 'ignore'.
|
|
1041
1091
|
// Allow is deliberately NOT applied — audit shows every finding.
|
|
1042
1092
|
const results = applySeverityFilter(rawResults, config);
|
|
1043
|
-
const effectiveSettings = await resolveEffectiveSettings(options, scanPath, logger);
|
|
1044
1093
|
// Run compatibility analysis if --compat flag is set
|
|
1045
1094
|
const compatMap = options.compat
|
|
1046
|
-
? await runCompatAnalysis(results, logger, scanRoot,
|
|
1095
|
+
? await runCompatAnalysis(results, logger, scanRoot, await resolveEffectiveSettings(options, scanPath), vatContextForCompat)
|
|
1047
1096
|
: undefined;
|
|
1048
1097
|
const verbose = options.verbose ?? false;
|
|
1049
1098
|
return {
|
|
1050
1099
|
results,
|
|
1051
|
-
|
|
1100
|
+
report: buildAuditDocument(results, {
|
|
1101
|
+
root: scanRoot,
|
|
1102
|
+
compatMap,
|
|
1103
|
+
verbose,
|
|
1104
|
+
hierarchical: null,
|
|
1105
|
+
durationMs: Date.now() - startTime,
|
|
1106
|
+
}),
|
|
1052
1107
|
};
|
|
1053
1108
|
}
|
|
1054
|
-
/**
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1109
|
+
/**
|
|
1110
|
+
* A URL audit's report: its run root is a random tempdir — not reproducible and
|
|
1111
|
+
* useless to a reader — so `data.root` is `null`, `data.provenance` states the
|
|
1112
|
+
* base instead (url @ ref @ commit), and any string still spelling the tempdir
|
|
1113
|
+
* is rewritten relative to the clone.
|
|
1114
|
+
*/
|
|
1115
|
+
export function urlAuditReport(report, provenance, tempRoot) {
|
|
1116
|
+
const rewritten = rewritePathsInResults(report, tempRoot);
|
|
1117
|
+
return { ...rewritten, data: { ...rewritten.data, root: null, provenance } };
|
|
1059
1118
|
}
|
|
1060
|
-
|
|
1119
|
+
/**
|
|
1120
|
+
* Audit `scanPath` and build the report, without publishing it: a URL audit publishes it only
|
|
1121
|
+
* once its clone is disposed of, so a clone left behind is a warning IN the document.
|
|
1122
|
+
*/
|
|
1123
|
+
async function buildAuditAtPath(scanPath, options, overrides = {}) {
|
|
1061
1124
|
const logger = createLogger(options.debug ? { debug: true } : {});
|
|
1062
1125
|
const startTime = Date.now();
|
|
1063
1126
|
const verbose = options.verbose ?? false;
|
|
1064
|
-
const { results,
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1127
|
+
const { results, report } = await buildAuditReport(scanPath, options, startTime, logger);
|
|
1128
|
+
const scanRoot = deriveScanRoot(scanPath);
|
|
1129
|
+
if (overrides.provenance !== undefined) {
|
|
1130
|
+
// The human half of the provenance: the machine half is `data.provenance`.
|
|
1131
|
+
logger.info(renderProvenanceHeader(overrides.provenance).trimEnd());
|
|
1132
|
+
}
|
|
1133
|
+
const published = overrides.provenance === undefined || overrides.tempRoot === undefined
|
|
1134
|
+
? report
|
|
1135
|
+
: urlAuditReport(report, overrides.provenance, overrides.tempRoot);
|
|
1136
|
+
return { results, report: published, scanRoot, logger, verbose, startTime };
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Publish a built audit, with `added` findings the run learned of after building it.
|
|
1140
|
+
*
|
|
1141
|
+
* @returns What was published. The caller exits with the code it calls for.
|
|
1142
|
+
*/
|
|
1143
|
+
function publishAudit(built, added) {
|
|
1144
|
+
const { results, scanRoot, logger, verbose } = built;
|
|
1145
|
+
const report = withAddedFindings(built.report, added);
|
|
1146
|
+
const written = writeDocument('audit', report, 'yaml');
|
|
1074
1147
|
if (verbose) {
|
|
1075
|
-
renderVerboseEvidence(results,
|
|
1148
|
+
renderVerboseEvidence(results, scanRoot, logger);
|
|
1076
1149
|
}
|
|
1077
|
-
handleAuditResults(results,
|
|
1078
|
-
logger.debug(`Audit complete in ${Date.now() - startTime}ms`);
|
|
1150
|
+
handleAuditResults({ results, written, data: report.data, root: scanRoot, verbose }, logger);
|
|
1151
|
+
logger.debug(`Audit complete in ${Date.now() - built.startTime}ms`);
|
|
1152
|
+
return written;
|
|
1079
1153
|
}
|
|
1080
1154
|
async function runUrlAudit(rawInput, options) {
|
|
1081
|
-
|
|
1082
|
-
|
|
1155
|
+
let parsed;
|
|
1156
|
+
try {
|
|
1157
|
+
parsed = parseGitUrl(rawInput);
|
|
1158
|
+
}
|
|
1159
|
+
catch (error) {
|
|
1160
|
+
// The argument is the operator's, and it does not name a source.
|
|
1161
|
+
throw new CommandRefusalError('USAGE_INVALID', errorMessageOf(error), { cause: error });
|
|
1162
|
+
}
|
|
1163
|
+
const { value: built, leftover } = await withClonedRepo(parsed, { keepTempForDebug: options.debug === true }, ({ targetDir, tempdir, provenance }) => {
|
|
1083
1164
|
// Re-enter the audit pipeline against the cloned target. Strip --user
|
|
1084
1165
|
// (it doesn't apply to URL audits).
|
|
1085
1166
|
const innerOptions = { ...options, user: false };
|
|
1086
|
-
|
|
1167
|
+
return buildAuditAtPath(targetDir, innerOptions, {
|
|
1087
1168
|
provenance,
|
|
1088
1169
|
tempRoot: tempdir,
|
|
1089
1170
|
});
|
|
1090
1171
|
});
|
|
1172
|
+
// Only now, the clone disposed of: one it left behind is a warning in the document.
|
|
1173
|
+
const written = publishAudit(built, leftover === undefined ? [] : toFindings([leftoverIssueOf(leftover)]));
|
|
1174
|
+
process.exit(exitCodeForReport(written));
|
|
1091
1175
|
}
|
|
1092
1176
|
export async function auditCommand(targetPath, options) {
|
|
1093
1177
|
const logger = createLogger(options.debug ? { debug: true } : {});
|
|
1094
1178
|
const startTime = Date.now();
|
|
1095
1179
|
resetAuditCaches();
|
|
1096
1180
|
try {
|
|
1181
|
+
refuseUnusableSettingsFlag(options);
|
|
1097
1182
|
// A local path always wins. `isGitUrl` accepts bare `owner/repo` GitHub
|
|
1098
1183
|
// shorthand, which is indistinguishable from an ordinary two-segment
|
|
1099
1184
|
// relative path (`plugins/arc`, `docs/guides`, `packages/cli`). Asking
|
|
@@ -1101,7 +1186,9 @@ export async function auditCommand(targetPath, options) {
|
|
|
1101
1186
|
// cloned https://github.com/<that>.git instead, reaching out to the
|
|
1102
1187
|
// network with a name derived from the caller's own directory layout.
|
|
1103
1188
|
// Shorthand is a fallback for arguments that name nothing on disk.
|
|
1104
|
-
|
|
1189
|
+
// The operator's own argument: its own `within`. A probe the OS refuses is its source fault,
|
|
1190
|
+
// never "names nothing on disk" — that would send a local path to the network.
|
|
1191
|
+
if (targetPath !== undefined && !pathPresent(targetPath, { follow: targetPath }, everywhere('source'), 'probe') && isGitUrl(targetPath)) {
|
|
1105
1192
|
await runUrlAudit(targetPath, options);
|
|
1106
1193
|
return;
|
|
1107
1194
|
}
|
|
@@ -1112,19 +1199,14 @@ export async function auditCommand(targetPath, options) {
|
|
|
1112
1199
|
return;
|
|
1113
1200
|
}
|
|
1114
1201
|
const scanPath = targetPath ? safePath.resolve(targetPath) : process.cwd();
|
|
1115
|
-
const unusable = await
|
|
1116
|
-
if (unusable !== undefined)
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
return handleExpectedFailure(unusable, ExitCode.ERROR, startTime);
|
|
1120
|
-
}
|
|
1121
|
-
await runAuditAtPath(scanPath, options);
|
|
1202
|
+
const unusable = await unusableRootRefusal(scanPath);
|
|
1203
|
+
if (unusable !== undefined)
|
|
1204
|
+
throw unusable;
|
|
1205
|
+
process.exit(exitCodeForReport(publishAudit(await buildAuditAtPath(scanPath, options), [])));
|
|
1122
1206
|
}
|
|
1123
1207
|
catch (error) {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
// operator has to search for did not match what they typed.
|
|
1127
|
-
handleCommandError(error, logger, startTime, 'Audit');
|
|
1208
|
+
logger.debug(`Audit did not finish after ${Date.now() - startTime}ms`);
|
|
1209
|
+
endWithRefusal('audit', refusalCodeOf(error), error, 'yaml', AUDIT_GATE, NOTHING_FINISHED);
|
|
1128
1210
|
}
|
|
1129
1211
|
}
|
|
1130
1212
|
/**
|
|
@@ -1132,42 +1214,49 @@ export async function auditCommand(targetPath, options) {
|
|
|
1132
1214
|
* may start.
|
|
1133
1215
|
*
|
|
1134
1216
|
* The exit-code contract every verb shares: a path that does not exist, or a
|
|
1135
|
-
* file no audit lane recognises, is the INVOCATION's mistake — `
|
|
1136
|
-
* (2) before any scan, the same ending `vat resources validate` and
|
|
1137
|
-
* review` give the same argument. Until this check the audit ran anyway and
|
|
1217
|
+
* file no audit lane recognises, is the INVOCATION's mistake — a `USAGE_INVALID`
|
|
1218
|
+
* refusal (exit 2) before any scan, the same ending `vat resources validate` and
|
|
1219
|
+
* `vat skill review` give the same argument. Until this check the audit ran anyway and
|
|
1138
1220
|
* published `UNKNOWN_FORMAT` as a finding at exit 1 with `filesScanned: 1`: a
|
|
1139
1221
|
* typo in a CI step read as "the tree failed its gate", and the denominator
|
|
1140
1222
|
* counted a file that was never there.
|
|
1141
1223
|
*
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1224
|
+
* 🚨 **And a root DIRECTORY the OS refuses to list.** It used to be left to
|
|
1225
|
+
* the scan, which degraded it to `SCAN_PATH_UNREADABLE` and ended on the
|
|
1226
|
+
* zero-files refusal at exit 1 — while `vat resources validate`, `check`,
|
|
1227
|
+
* `query` and `scan` all end the same argument at exit 2. One outcome, two
|
|
1228
|
+
* codes. Nothing under an unlistable root can be examined, so the audit could
|
|
1229
|
+
* not do its job: an `INPUT_UNREADABLE` refusal, exit 2 like a missing path.
|
|
1230
|
+
*
|
|
1231
|
+
* ONLY the root. A sub-path inside a readable tree is never the invocation's
|
|
1232
|
+
* fault and stays a finding. Pinned by the `audit → error` rows of
|
|
1233
|
+
* `exit-codes.system.test.ts` and the `audit` row of
|
|
1234
|
+
* `exit-code-matrix-path-unlistable.system.test.ts`.
|
|
1148
1235
|
*/
|
|
1149
|
-
async function
|
|
1236
|
+
async function unusableRootRefusal(scanPath) {
|
|
1150
1237
|
let isDirectory;
|
|
1151
1238
|
try {
|
|
1152
1239
|
isDirectory = fs.lstatSync(scanPath).isDirectory();
|
|
1153
1240
|
}
|
|
1154
1241
|
catch (error) {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
return
|
|
1242
|
+
// Absent is the invocation's mistake; any other error (an `EACCES` parent) is
|
|
1243
|
+
// the input's refusal — never a scan that starts anyway.
|
|
1244
|
+
return classifyInputFault(scanPath, error, { origin: 'argument', message: `Path does not exist: ${scanPath}` });
|
|
1158
1245
|
}
|
|
1159
|
-
if (isDirectory
|
|
1246
|
+
if (isDirectory)
|
|
1247
|
+
return unlistableDirectoryRefusal(scanPath);
|
|
1248
|
+
if (detectFormat(scanPath) === RESOURCE_TYPE_AGENT_SKILL)
|
|
1160
1249
|
return undefined;
|
|
1161
1250
|
if ((await detectResourceFormat(scanPath)).type !== 'unknown')
|
|
1162
1251
|
return undefined;
|
|
1163
|
-
return `Path is not a resource this command can audit (a SKILL.md, a plugin or marketplace directory, or a Claude registry file): ${scanPath}
|
|
1252
|
+
return new CommandRefusalError('USAGE_INVALID', `Path is not a resource this command can audit (a SKILL.md, a plugin or marketplace directory, or a Claude registry file): ${scanPath}`);
|
|
1164
1253
|
}
|
|
1165
1254
|
/**
|
|
1166
1255
|
* Dispatch a single surface to the matching validator. Keeps the multi-surface
|
|
1167
1256
|
* branch of {@link getValidationResults} focused so cognitive complexity stays
|
|
1168
1257
|
* within the ESLint budget.
|
|
1169
1258
|
*/
|
|
1170
|
-
|
|
1259
|
+
function validateSurface(surface, options, logger, locationRoot) {
|
|
1171
1260
|
if (surface.type === RESOURCE_TYPE_AGENT_SKILL) {
|
|
1172
1261
|
// No crawl: this arm only runs for a MULTI-surface root, which in practice is
|
|
1173
1262
|
// skill-claude-plugin (SKILL.md beside .claude-plugin/plugin.json). The plugin
|
|
@@ -1184,13 +1273,10 @@ async function validateSurface(surface, options, logger, locationRoot) {
|
|
|
1184
1273
|
* Validate every surface enumerated at a directory root (used when
|
|
1185
1274
|
* `enumerateSurfaces` returns more than one — e.g., skill-claude-plugin).
|
|
1186
1275
|
*/
|
|
1187
|
-
|
|
1276
|
+
function validateMultipleSurfaces(surfaces, scanPath, options, logger, locationRoot) {
|
|
1188
1277
|
logger.debug(`Detected ${surfaces.length.toString()} surfaces at ${scanPath}: ${surfaces.map((s) => s.type).join(', ')}`);
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
results.push(await validateSurface(surface, options, logger, locationRoot));
|
|
1192
|
-
}
|
|
1193
|
-
return results;
|
|
1278
|
+
// In order: the surfaces share the population cache and the logger.
|
|
1279
|
+
return mapInOrder(surfaces, (surface) => validateSurface(surface, options, logger, locationRoot));
|
|
1194
1280
|
}
|
|
1195
1281
|
/**
|
|
1196
1282
|
* Additive inventory-detector pass — runs the pure-function detectors
|
|
@@ -1234,18 +1320,19 @@ async function recurseIntoMarketplacePlugins(marketplaceInv, recursive, options,
|
|
|
1234
1320
|
const marketplaceRoot = safePath.resolve(marketplaceInv.path);
|
|
1235
1321
|
const seen = new Set([marketplaceRoot]);
|
|
1236
1322
|
const results = [];
|
|
1237
|
-
|
|
1323
|
+
// In order: the `seen` dedupe must see each plugin before the next one starts.
|
|
1324
|
+
await forEachInOrder(marketplaceInv.discovered.plugins, async (plugin) => {
|
|
1238
1325
|
const pluginPath = safePath.resolve(plugin.path);
|
|
1239
1326
|
if (seen.has(pluginPath)) {
|
|
1240
1327
|
logger.debug(` Skipping marketplace-recurse into already-visited path: ${pluginPath}`);
|
|
1241
|
-
|
|
1328
|
+
return;
|
|
1242
1329
|
}
|
|
1243
1330
|
seen.add(pluginPath);
|
|
1244
1331
|
logger.debug(` Recursing into marketplace path-source plugin: ${pluginPath}`);
|
|
1245
1332
|
// Same run root — recursing into a co-located plugin must NOT re-anchor.
|
|
1246
1333
|
const pluginResults = await getValidationResults(pluginPath, recursive, options, logger, locationRoot);
|
|
1247
1334
|
results.push(...pluginResults);
|
|
1248
|
-
}
|
|
1335
|
+
});
|
|
1249
1336
|
return results;
|
|
1250
1337
|
}
|
|
1251
1338
|
/**
|
|
@@ -1309,7 +1396,7 @@ function appendInventoryParseErrors(result, inv, locationRoot) {
|
|
|
1309
1396
|
refusalsFiled.add(location);
|
|
1310
1397
|
parseIssues.push(materializeIssue('SCAN_PATH_UNREADABLE', { location, detail: `${location}: ${message}` }));
|
|
1311
1398
|
}
|
|
1312
|
-
// Status was hand-set to 'error' here while
|
|
1399
|
+
// Status was hand-set to 'error' here while the counts and description kept
|
|
1313
1400
|
// describing the pre-append list. One appender derives all three.
|
|
1314
1401
|
appendIssues(result, parseIssues);
|
|
1315
1402
|
}
|
|
@@ -1352,7 +1439,7 @@ export async function getValidationResults(scanPath, recursive, options, logger,
|
|
|
1352
1439
|
catch (error) {
|
|
1353
1440
|
// Only the filesystem refusing the subject degrades; a defect in a validator
|
|
1354
1441
|
// must still fail loudly rather than be reported as a permissions problem.
|
|
1355
|
-
if (
|
|
1442
|
+
if (fsFaultOf(error) === undefined)
|
|
1356
1443
|
throw error;
|
|
1357
1444
|
logger.debug(`Unreadable audit subject: ${scanPath}`);
|
|
1358
1445
|
return [unreadablePathResult(scanPath, error, locationRoot)];
|
|
@@ -1426,13 +1513,10 @@ function withoutHostedRefusals(result, hosted) {
|
|
|
1426
1513
|
return [];
|
|
1427
1514
|
if (issues.length === result.issues.length)
|
|
1428
1515
|
return [result];
|
|
1429
|
-
const issueCounts = countBySeverity(issues);
|
|
1430
1516
|
return [{
|
|
1431
1517
|
...result,
|
|
1432
|
-
|
|
1433
|
-
summary: formatCountsSummary(issueCounts),
|
|
1518
|
+
...describeIssues(issues, result.type),
|
|
1434
1519
|
issues,
|
|
1435
|
-
issueCounts,
|
|
1436
1520
|
}];
|
|
1437
1521
|
}
|
|
1438
1522
|
async function validateAuditSubject(scanPath, recursive, options, logger, locationRoot) {
|
|
@@ -1499,7 +1583,7 @@ async function validateAuditSubject(scanPath, recursive, options, logger, locati
|
|
|
1499
1583
|
return [result];
|
|
1500
1584
|
}
|
|
1501
1585
|
// If unknown format, check if it's a directory we can scan
|
|
1502
|
-
if (await isScannableDirectory(scanPath)) {
|
|
1586
|
+
if (await isScannableDirectory(scanPath, locationRoot)) {
|
|
1503
1587
|
logger.debug('Scanning directory for resources');
|
|
1504
1588
|
// The project's `resources.exclude` is applied by the scan context,
|
|
1505
1589
|
// on the project-root basis its globs were written against — NOT
|
|
@@ -1527,10 +1611,10 @@ async function validateAuditSubject(scanPath, recursive, options, logger, locati
|
|
|
1527
1611
|
* `validate()` then reported the directory as an unknown resource format. A
|
|
1528
1612
|
* scan that examined nothing was reported as a directory that was nothing.
|
|
1529
1613
|
*/
|
|
1530
|
-
async function isScannableDirectory(scanPath) {
|
|
1531
|
-
const fsp = await import('node:fs/promises');
|
|
1614
|
+
async function isScannableDirectory(scanPath, locationRoot) {
|
|
1532
1615
|
try {
|
|
1533
|
-
|
|
1616
|
+
// `scanPath` is crawled beneath the run's scan root: its links are read before the kernel follows them.
|
|
1617
|
+
return (await followedKind(scanPath, locationRoot)) === 'directory';
|
|
1534
1618
|
}
|
|
1535
1619
|
catch (error) {
|
|
1536
1620
|
if (isPathAbsentError(error))
|
|
@@ -1550,11 +1634,12 @@ async function isScannableDirectory(scanPath) {
|
|
|
1550
1634
|
async function validatePluginSkillsViaInventory(scanPath, options, logger, locationRoot, excludeSkillPaths = new Set()) {
|
|
1551
1635
|
const inv = await pluginInventoryAt(scanPath);
|
|
1552
1636
|
const results = [];
|
|
1553
|
-
|
|
1637
|
+
// In order: the skills share the population cache and the logger.
|
|
1638
|
+
await forEachInOrder(inv.discovered.skills, async (skill) => {
|
|
1554
1639
|
const resolvedPath = safePath.resolve(skill.files.skillMd);
|
|
1555
1640
|
if (excludeSkillPaths.has(resolvedPath)) {
|
|
1556
1641
|
logger.debug(` Skipping already-validated skill (inventory): ${skill.files.skillMd}`);
|
|
1557
|
-
|
|
1642
|
+
return;
|
|
1558
1643
|
}
|
|
1559
1644
|
logger.debug(` Validating plugin-bundled skill (inventory): ${skill.files.skillMd}`);
|
|
1560
1645
|
// Guarded PER SKILL, not left to the boundary. The boundary guard answers at
|
|
@@ -1572,12 +1657,12 @@ async function validatePluginSkillsViaInventory(scanPath, options, logger, locat
|
|
|
1572
1657
|
results.push(await validateSingleSkill(skill.files.skillMd, options, logger, locationRoot, false));
|
|
1573
1658
|
}
|
|
1574
1659
|
catch (error) {
|
|
1575
|
-
if (
|
|
1660
|
+
if (fsFaultOf(error) === undefined)
|
|
1576
1661
|
throw error;
|
|
1577
1662
|
logger.debug(` Unreadable plugin-bundled skill: ${skill.files.skillMd}`);
|
|
1578
1663
|
results.push(unreadablePathResult(skill.files.skillMd, error, locationRoot));
|
|
1579
1664
|
}
|
|
1580
|
-
}
|
|
1665
|
+
});
|
|
1581
1666
|
return results;
|
|
1582
1667
|
}
|
|
1583
1668
|
/**
|
|
@@ -1643,9 +1728,10 @@ function withRelativePath(message, absolutePath, locationRoot) {
|
|
|
1643
1728
|
*/
|
|
1644
1729
|
export async function runCompatAnalysis(results, logger, locationRoot, effectiveSettings, vatContext = null) {
|
|
1645
1730
|
const compatMap = new Map();
|
|
1646
|
-
|
|
1731
|
+
// In order: each plugin's explanations go to the logger as it is analyzed.
|
|
1732
|
+
await forEachInOrder(results, async (result) => {
|
|
1647
1733
|
if (result.type !== RESOURCE_TYPE_CLAUDE_PLUGIN)
|
|
1648
|
-
|
|
1734
|
+
return;
|
|
1649
1735
|
const entry = {
|
|
1650
1736
|
compat: await analyzeOrExplain(result.path, locationRoot, vatContext, logger),
|
|
1651
1737
|
};
|
|
@@ -1653,9 +1739,31 @@ export async function runCompatAnalysis(results, logger, locationRoot, effective
|
|
|
1653
1739
|
entry.settings = await settingsVerdict(result.path, effectiveSettings, locationRoot, logger);
|
|
1654
1740
|
}
|
|
1655
1741
|
compatMap.set(result.path, entry);
|
|
1656
|
-
}
|
|
1742
|
+
});
|
|
1743
|
+
fileLaneFindings(results, compatMap, locationRoot);
|
|
1657
1744
|
return compatMap;
|
|
1658
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* File what the lanes found, and what they could not look at, as findings on each plugin's own
|
|
1748
|
+
* result — so the envelope's status, the row's status and the file counts say what the
|
|
1749
|
+
* `compatibility:` and `settings:` blocks say. A path whose refusal the document already carries
|
|
1750
|
+
* (by its code: `compatLaneIssues` decides which) is not filed a second time.
|
|
1751
|
+
*/
|
|
1752
|
+
function fileLaneFindings(results, compatMap, locationRoot) {
|
|
1753
|
+
const locationOf = (absolutePath) => issueLocation(absolutePath, locationRoot) || '.';
|
|
1754
|
+
const filed = results.flatMap((result) => result.issues.map((issue) => ({ code: issue.code, location: issue.location ?? locationOf(result.path) })));
|
|
1755
|
+
for (const result of results) {
|
|
1756
|
+
const entry = compatMap.get(result.path);
|
|
1757
|
+
if (entry === undefined)
|
|
1758
|
+
continue;
|
|
1759
|
+
const issues = compatLaneIssues(locationOf(result.path), {
|
|
1760
|
+
compatibility: entry.compat,
|
|
1761
|
+
...(entry.settings !== undefined && { settings: renderSettingsBlock(entry.settings, locationRoot) }),
|
|
1762
|
+
}, filed);
|
|
1763
|
+
appendIssues(result, issues);
|
|
1764
|
+
filed.push(...issues.map((issue) => ({ code: issue.code, location: issue.location ?? locationOf(result.path) })));
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1659
1767
|
/**
|
|
1660
1768
|
* The analyzer's result for one plugin, or — when it threw — the reason, said
|
|
1661
1769
|
* on stderr and carried into the document. Compat analysis is best-effort:
|
|
@@ -1743,45 +1851,65 @@ function applyCompatMap(results, compatMap, locationRoot) {
|
|
|
1743
1851
|
return results;
|
|
1744
1852
|
}
|
|
1745
1853
|
/**
|
|
1746
|
-
*
|
|
1747
|
-
*
|
|
1748
|
-
* (even as `[]`) would clutter terse YAML; we omit the key entirely.
|
|
1854
|
+
* `compatibility.evidence` is published only under `--verbose`. Producing the
|
|
1855
|
+
* field at all (even as `[]`) would clutter terse YAML; the key is omitted.
|
|
1749
1856
|
*/
|
|
1750
1857
|
function stripCompatEvidence(compat) {
|
|
1751
1858
|
const out = { ...compat };
|
|
1752
1859
|
delete out['evidence'];
|
|
1753
1860
|
return out;
|
|
1754
1861
|
}
|
|
1755
|
-
function applyVerboseFilter(results, verbose) {
|
|
1756
|
-
if (verbose)
|
|
1757
|
-
return results;
|
|
1758
|
-
return results.map(r => {
|
|
1759
|
-
const stripped = { ...r };
|
|
1760
|
-
delete stripped['evidence'];
|
|
1761
|
-
if (r.compatibility !== undefined) {
|
|
1762
|
-
stripped['compatibility'] = stripCompatEvidence(r.compatibility);
|
|
1763
|
-
}
|
|
1764
|
-
return stripped;
|
|
1765
|
-
});
|
|
1766
|
-
}
|
|
1767
1862
|
/**
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1863
|
+
* A result's row. `status` and `summary` are re-derived from its FINAL issue
|
|
1864
|
+
* list here — a producer that appended findings after publishing its counts
|
|
1865
|
+
* cannot leave the row describing the list as it was.
|
|
1866
|
+
*/
|
|
1867
|
+
function fileRow(result, root, verbose) {
|
|
1868
|
+
const row = { path: relativizePath(result.path, root), type: result.type, ...summarizeIssues(result.issues) };
|
|
1869
|
+
if (result.compatibility !== undefined)
|
|
1870
|
+
row.compatibility = verbose ? result.compatibility : stripCompatEvidence(result.compatibility);
|
|
1871
|
+
if (result.settings !== undefined)
|
|
1872
|
+
row.settings = result.settings;
|
|
1873
|
+
return row;
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Every file's findings, flattened, each naming the file to open. A finding a
|
|
1877
|
+
* validator published without a `location` inherits its file's row path, so a
|
|
1878
|
+
* consumer never has to join a finding back to the row it came from.
|
|
1879
|
+
*/
|
|
1880
|
+
function auditFindings(results, root) {
|
|
1881
|
+
return toFindings(results.flatMap((result) => result.issues.map((issue) => issue.location === undefined ? { ...issue, location: relativizePath(result.path, root) } : issue)));
|
|
1882
|
+
}
|
|
1883
|
+
/**
|
|
1884
|
+
* Assemble the report envelope from the per-file results.
|
|
1885
|
+
*
|
|
1886
|
+
* ONE builder for the directory lane, the `--user` lane and the corpus scan's
|
|
1887
|
+
* per-plugin document, so none of them can publish a status or a count the
|
|
1888
|
+
* others would not. `examined` is the files READ — a refused path is counted
|
|
1889
|
+
* in `data.counts.pathsUnreadable` and nowhere else — and the writer turns a
|
|
1890
|
+
* zero into the run's `RESOURCE_CHECK_BROKEN` finding.
|
|
1891
|
+
*
|
|
1892
|
+
* @param results - One result per audited file or refused path
|
|
1893
|
+
* @param context - The root, the compat lanes' output and the `--user` view
|
|
1894
|
+
* @returns The report, before the writer's run-integrity pass
|
|
1895
|
+
*/
|
|
1896
|
+
export function buildAuditDocument(results, context) {
|
|
1897
|
+
const { root, compatMap, verbose, hierarchical, durationMs } = context;
|
|
1898
|
+
const { examined, counts } = countFilesByStatus(results);
|
|
1899
|
+
return buildReport({
|
|
1900
|
+
examined,
|
|
1901
|
+
findings: auditFindings(results, root),
|
|
1902
|
+
data: {
|
|
1903
|
+
// Stated once, and the only absolute path in the document.
|
|
1904
|
+
root,
|
|
1905
|
+
provenance: null,
|
|
1906
|
+
counts,
|
|
1907
|
+
files: applyCompatMap([...results], compatMap, root).map((result) => fileRow(result, root, verbose)),
|
|
1908
|
+
hierarchical,
|
|
1909
|
+
},
|
|
1910
|
+
gate: AUDIT_GATE,
|
|
1911
|
+
durationMs,
|
|
1912
|
+
});
|
|
1785
1913
|
}
|
|
1786
1914
|
/**
|
|
1787
1915
|
* Maps a CAPABILITY_* observation code to the family of pattern IDs whose
|
|
@@ -1879,21 +2007,22 @@ function renderVerboseEvidence(results, root, logger) {
|
|
|
1879
2007
|
}
|
|
1880
2008
|
}
|
|
1881
2009
|
/**
|
|
1882
|
-
* The stderr half of
|
|
1883
|
-
* document says. The
|
|
1884
|
-
*
|
|
1885
|
-
*
|
|
1886
|
-
*
|
|
1887
|
-
*
|
|
2010
|
+
* The stderr half of the run-level refusal, so the human channel says what the
|
|
2011
|
+
* document says. The writer derives it (the registry's denominator for `audit`
|
|
2012
|
+
* is files); this only RENDERS the finding the WRITTEN report carries. Both
|
|
2013
|
+
* stderr lanes call it first, because "Audit successful: 0 file(s) passed"
|
|
2014
|
+
* over a refused run is the exact disagreement the refusal exists to end
|
|
2015
|
+
* (invariant 6 of `run-integrity.ts`).
|
|
1888
2016
|
*
|
|
1889
2017
|
* @returns Whether a refusal was rendered, so the caller skips its verdict line
|
|
1890
2018
|
*/
|
|
1891
|
-
function logRunIntegrity(
|
|
1892
|
-
|
|
2019
|
+
function logRunIntegrity(written, logger) {
|
|
2020
|
+
const refusals = written.findings.filter((finding) => finding.code === RUN_INTEGRITY_CODE);
|
|
2021
|
+
if (refusals.length === 0)
|
|
1893
2022
|
return false;
|
|
1894
|
-
logger.error(
|
|
1895
|
-
for (const
|
|
1896
|
-
for (const line of formatIssueLines(
|
|
2023
|
+
logger.error(`Audit is not a verdict: it audited ${written.examined} files`);
|
|
2024
|
+
for (const refusal of refusals) {
|
|
2025
|
+
for (const line of formatIssueLines(refusal, ' '))
|
|
1897
2026
|
logger.error(line);
|
|
1898
2027
|
}
|
|
1899
2028
|
return true;
|
|
@@ -1933,36 +2062,34 @@ function logSettingsTotals(files, logger) {
|
|
|
1933
2062
|
logger.error(`⚠ ${compatUnchecked} path(s) the compatibility analysis could not read — see 'compatibility.unchecked' in YAML output`);
|
|
1934
2063
|
}
|
|
1935
2064
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
if (refused) {
|
|
2065
|
+
/**
|
|
2066
|
+
* The human channel for the directory lane, read off the WRITTEN report — the
|
|
2067
|
+
* file counts, and the findings of the files that carry an actionable one. The
|
|
2068
|
+
* exit code is not decided here: the caller ends on `exitCodeForReport`.
|
|
2069
|
+
*/
|
|
2070
|
+
function handleAuditResults({ results, written, data, root, verbose }, logger) {
|
|
2071
|
+
const { filesWithErrors: errorCount, filesWithWarnings: warningCount, filesPassed: successCount, } = data.counts;
|
|
2072
|
+
logSettingsTotals(data.files, logger);
|
|
2073
|
+
if (logRunIntegrity(written, logger)) {
|
|
1946
2074
|
// Rendered above; there is no file verdict to print over zero files.
|
|
1947
2075
|
}
|
|
1948
2076
|
else if (errorCount > 0) {
|
|
1949
2077
|
logger.error(`Audit found ${errorCount} file(s) with errors`);
|
|
1950
|
-
logFindingsForStatus(results,
|
|
2078
|
+
logFindingsForStatus(results, hasErrors, root, logger.error.bind(logger), verbose);
|
|
1951
2079
|
}
|
|
1952
2080
|
else if (warningCount > 0) {
|
|
1953
2081
|
logger.info(`Audit passed with warnings: ${warningCount} file(s)`);
|
|
1954
|
-
logFindingsForStatus(results,
|
|
2082
|
+
logFindingsForStatus(results, hasOnlyWarnings, root, logger.info.bind(logger), verbose);
|
|
1955
2083
|
}
|
|
1956
2084
|
else {
|
|
1957
|
-
// `
|
|
1958
|
-
//
|
|
2085
|
+
// `ok` over info findings still means "nothing actionable", NOT "nothing
|
|
2086
|
+
// to see" — name them or the YAML and the stderr line disagree.
|
|
1959
2087
|
const withFindings = countResultsWithFindings(results);
|
|
1960
2088
|
logger.info(withFindings > 0
|
|
1961
2089
|
? `Audit successful: ${successCount} file(s) passed (${withFindings} with informational findings)`
|
|
1962
2090
|
: `Audit successful: ${successCount} file(s) passed`);
|
|
1963
2091
|
}
|
|
1964
2092
|
renderAuditFooter(results, logger);
|
|
1965
|
-
process.exit(refused || errorCount > 0 ? ExitCode.FINDINGS : ExitCode.OK);
|
|
1966
2093
|
}
|
|
1967
2094
|
/**
|
|
1968
2095
|
* Render the skill-quality checklist footer when audit results contain
|
|
@@ -2015,7 +2142,7 @@ function renderAuditFooter(results, logger) {
|
|
|
2015
2142
|
* cannot answer the question.
|
|
2016
2143
|
*
|
|
2017
2144
|
* Pure: takes results, returns lines. It reads `issues` and never rewrites it,
|
|
2018
|
-
* because `
|
|
2145
|
+
* because `buildAuditAtPath` builds the YAML document from the very same array.
|
|
2019
2146
|
*
|
|
2020
2147
|
* @internal Exported for unit testing only — not part of the public CLI API.
|
|
2021
2148
|
*/
|
|
@@ -2051,8 +2178,8 @@ export function formatAuditFindingsLines(results, root, verbose) {
|
|
|
2051
2178
|
* The banner counts FILES and the blocks below count FINDINGS; both are needed,
|
|
2052
2179
|
* and `logFn` picks the channel the calling branch already established.
|
|
2053
2180
|
*/
|
|
2054
|
-
function logFindingsForStatus(results,
|
|
2055
|
-
const selected = results.filter(
|
|
2181
|
+
function logFindingsForStatus(results, inBucket, root, logFn, verbose) {
|
|
2182
|
+
const selected = results.filter(inBucket);
|
|
2056
2183
|
for (const line of formatAuditFindingsLines(selected, root, verbose)) {
|
|
2057
2184
|
logFn(line);
|
|
2058
2185
|
}
|
|
@@ -2134,15 +2261,16 @@ async function handleFileEntry(entry, fullPath, options, logger, scanCtx) {
|
|
|
2134
2261
|
const skillDir = safePath.resolve(fullPath, '..');
|
|
2135
2262
|
const unreadable = degradingRegistry(findProjectRoot(skillDir) ?? skillDir, logger, locationRoot);
|
|
2136
2263
|
const sharedCtx = scanCtx.gitTracker === null
|
|
2137
|
-
? { locationRoot, projectSkills, suiteProbe, unreadable }
|
|
2138
|
-
: { gitTracker: scanCtx.gitTracker, locationRoot, projectSkills, suiteProbe, unreadable };
|
|
2264
|
+
? { locationRoot, projectSkills, suiteProbe, unreadable, outputs: [] }
|
|
2265
|
+
: { gitTracker: scanCtx.gitTracker, locationRoot, projectSkills, suiteProbe, unreadable, outputs: [] };
|
|
2139
2266
|
const packagingResult = await validateSkillForPackaging(fullPath, skillConfig, 'source', sharedCtx);
|
|
2140
2267
|
const configAware = packagingResultToValidationResult(fullPath, packagingResult, skillConfig.targets, locationRoot);
|
|
2141
2268
|
await appendDistributedTreeFindings(configAware, fullPath, locationRoot, ownsOwnCrawl(scanCtx, fullPath));
|
|
2142
2269
|
return configAware;
|
|
2143
2270
|
}
|
|
2144
2271
|
// Wild mode: basic validation. Severity is applied by `applySeverityFilter`.
|
|
2145
|
-
|
|
2272
|
+
// The audited skill is the verb's input.
|
|
2273
|
+
const validateOptions = { skillPath: fullPath, locationRoot, validation: {}, side: 'source' };
|
|
2146
2274
|
if (options.warnUnreferencedFiles) {
|
|
2147
2275
|
validateOptions.checkUnreferencedFiles = true;
|
|
2148
2276
|
}
|
|
@@ -2179,7 +2307,7 @@ async function validatePluginDirectory(dir, logger, locationRoot) {
|
|
|
2179
2307
|
*/
|
|
2180
2308
|
const inventoryRegistryCache = new Map();
|
|
2181
2309
|
/** Build (once per run, per root) the registry the plugin inventory link walk needs. */
|
|
2182
|
-
|
|
2310
|
+
function getOrCreateInventoryRegistry(projectRoot) {
|
|
2183
2311
|
const cached = inventoryRegistryCache.get(projectRoot);
|
|
2184
2312
|
if (cached !== undefined) {
|
|
2185
2313
|
return cached;
|
|
@@ -2215,7 +2343,7 @@ async function getOrCreateInventoryRegistry(projectRoot) {
|
|
|
2215
2343
|
* case to encode here. This is the call site that carried all 786 measured
|
|
2216
2344
|
* `git check-ignore` spawns.
|
|
2217
2345
|
*/
|
|
2218
|
-
|
|
2346
|
+
function pluginInventoryAt(dir) {
|
|
2219
2347
|
const projectRoot = findProjectRoot(dir);
|
|
2220
2348
|
return extractClaudePluginInventory(dir, {
|
|
2221
2349
|
...(projectRoot === null
|
|
@@ -2280,11 +2408,11 @@ async function resolveScanContext(dirPath, locationRoot, logger) {
|
|
|
2280
2408
|
* is no longer the ONLY thing the run says — the code, the location and the fix
|
|
2281
2409
|
* come from the registry.
|
|
2282
2410
|
*
|
|
2283
|
-
* This result is a `files[]` row but NOT a
|
|
2411
|
+
* This result is a `data.files[]` row but NOT a file read: `countFilesByStatus`
|
|
2284
2412
|
* recognises it ({@link isUnreadablePathResult}) and reports it under
|
|
2285
|
-
* `
|
|
2286
|
-
* root the OS refused therefore
|
|
2287
|
-
* refusal, instead of `
|
|
2413
|
+
* `data.counts.pathsUnreadable`, outside `examined` and the status counts. A
|
|
2414
|
+
* root the OS refused therefore examines zero files and ends on the zero-files
|
|
2415
|
+
* refusal, instead of `examined: 1` over a path nothing read.
|
|
2288
2416
|
*/
|
|
2289
2417
|
function unreadablePathResult(dirPath, error, locationRoot) {
|
|
2290
2418
|
// `issueLocation` is `path.relative`, so it answers `''` when the subject IS the
|
|
@@ -2305,14 +2433,11 @@ function unreadablePathResult(dirPath, error, locationRoot) {
|
|
|
2305
2433
|
detail: `${location}: ${reason}`,
|
|
2306
2434
|
}),
|
|
2307
2435
|
];
|
|
2308
|
-
const issueCounts = countBySeverity(issues);
|
|
2309
2436
|
return {
|
|
2310
2437
|
path: dirPath,
|
|
2311
2438
|
type: 'unknown',
|
|
2312
|
-
|
|
2313
|
-
summary: formatCountsSummary(issueCounts),
|
|
2439
|
+
...describeIssues(issues, 'unknown'),
|
|
2314
2440
|
issues,
|
|
2315
|
-
issueCounts,
|
|
2316
2441
|
};
|
|
2317
2442
|
}
|
|
2318
2443
|
/**
|
|
@@ -2342,7 +2467,7 @@ async function validateScanSubject(subject, options, logger, scanCtx, claims) {
|
|
|
2342
2467
|
}
|
|
2343
2468
|
const subjectCtx = { ...scanCtx, crawledRoot: claims.owner(subject.path) };
|
|
2344
2469
|
const result = await handleFileEntry({ name: basename(subject.path) }, subject.path, options, logger, subjectCtx);
|
|
2345
|
-
if (subject.kind === 'skill' && ownsOwnCrawl(subjectCtx, subject.path) && await crawlOwnsSubtree(subject.path)) {
|
|
2470
|
+
if (subject.kind === 'skill' && ownsOwnCrawl(subjectCtx, subject.path) && await crawlOwnsSubtree(subject.path, locationRoot)) {
|
|
2346
2471
|
claims.claim(subject.dir);
|
|
2347
2472
|
}
|
|
2348
2473
|
return result === null ? [] : [result];
|
|
@@ -2352,7 +2477,7 @@ async function validateScanSubject(subject, options, logger, scanCtx, claims) {
|
|
|
2352
2477
|
// turning a genuine VAT bug into a `warning` about the file it happened on is
|
|
2353
2478
|
// the same "detector silently disables itself" shape this guard exists to
|
|
2354
2479
|
// prevent — it would make the tool quietest exactly when it is most wrong.
|
|
2355
|
-
if (
|
|
2480
|
+
if (fsFaultOf(error) === undefined)
|
|
2356
2481
|
throw error;
|
|
2357
2482
|
const path = subject.kind === 'plugin' ? subject.dir : subject.path;
|
|
2358
2483
|
logger.debug(`Unreadable entry: ${path}`);
|
|
@@ -2403,29 +2528,16 @@ async function scanDirectory(dirPath, recursive, options, logger, scanCtx) {
|
|
|
2403
2528
|
}
|
|
2404
2529
|
const results = population.refusals.map((refusal) => {
|
|
2405
2530
|
logger.debug(`Unreadable directory: ${refusal.directory}`);
|
|
2406
|
-
const err = new DirectoryListingRefusedError(refusal, { root: dirPath, remedy: scanRefusalRemedy() });
|
|
2531
|
+
const err = new DirectoryListingRefusedError(refusal, { root: dirPath, remedy: scanRefusalRemedy(), side: 'source' });
|
|
2407
2532
|
return unreadablePathResult(refusal.directory, err, scanCtx.locationRoot);
|
|
2408
2533
|
});
|
|
2409
2534
|
const claims = new SubtreeClaims();
|
|
2410
|
-
|
|
2535
|
+
// In order: `claims` resolves each subtree against the subjects before it.
|
|
2536
|
+
await forEachInOrder(population.subjects, async (subject) => {
|
|
2411
2537
|
results.push(...await validateScanSubject(subject, options, logger, scanCtx, claims));
|
|
2412
|
-
}
|
|
2538
|
+
});
|
|
2413
2539
|
return results;
|
|
2414
2540
|
}
|
|
2415
|
-
/**
|
|
2416
|
-
* Calculate overall status from validation results
|
|
2417
|
-
*/
|
|
2418
|
-
function calculateOverallStatus(results) {
|
|
2419
|
-
const errorCount = results.filter((r) => r.status === 'error').length;
|
|
2420
|
-
const warningCount = results.filter((r) => r.status === 'warning').length;
|
|
2421
|
-
if (errorCount > 0) {
|
|
2422
|
-
return 'error';
|
|
2423
|
-
}
|
|
2424
|
-
if (warningCount > 0) {
|
|
2425
|
-
return 'warning';
|
|
2426
|
-
}
|
|
2427
|
-
return 'success';
|
|
2428
|
-
}
|
|
2429
2541
|
/**
|
|
2430
2542
|
* How many results carry at least one finding.
|
|
2431
2543
|
*
|
|
@@ -2449,147 +2561,53 @@ function isUnreadablePathResult(result) {
|
|
|
2449
2561
|
&& result.issues.every((issue) => issue.code === 'SCAN_PATH_UNREADABLE');
|
|
2450
2562
|
}
|
|
2451
2563
|
/**
|
|
2452
|
-
* Count files by their
|
|
2564
|
+
* Count files by their worst actionable severity, and the files read.
|
|
2453
2565
|
*
|
|
2454
2566
|
* A refused path is NOT a scanned file. It used to be counted as one, which
|
|
2455
2567
|
* made the zero-files refusal unreachable for exactly the tree it exists for:
|
|
2456
|
-
* `chmod 000` on the whole root gave
|
|
2457
|
-
*
|
|
2458
|
-
*
|
|
2568
|
+
* `chmod 000` on the whole root gave one file scanned, none passed, a warning
|
|
2569
|
+
* status and exit 0 — nothing read, gate green. Kept out of every status count
|
|
2570
|
+
* too, or `filesWithWarnings` would exceed the files read.
|
|
2459
2571
|
*/
|
|
2460
2572
|
function countFilesByStatus(results) {
|
|
2461
2573
|
const scanned = results.filter((r) => !isUnreadablePathResult(r));
|
|
2574
|
+
const withErrors = scanned.filter(hasErrors).length;
|
|
2575
|
+
const withWarnings = scanned.filter(hasOnlyWarnings).length;
|
|
2462
2576
|
return {
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
}
|
|
2470
|
-
/**
|
|
2471
|
-
* Build base summary structure (used by both flat and hierarchical), together
|
|
2472
|
-
* with the entries the document will publish.
|
|
2473
|
-
*
|
|
2474
|
-
* `issueCounts` is named exactly as it is on every individual file entry, and
|
|
2475
|
-
* means the same thing at both levels: findings, by severity. `summary` only ever
|
|
2476
|
-
* counts files.
|
|
2477
|
-
*
|
|
2478
|
-
* The header total and every per-file total come from ONE traversal of the
|
|
2479
|
-
* final issue set, and the entries carrying those per-file totals are returned
|
|
2480
|
-
* from the same pass. Before that, the header was derived from the issue
|
|
2481
|
-
* records while each file's `issueCounts` was whatever its producer had
|
|
2482
|
-
* published — and a producer that appends findings after publishing (or never
|
|
2483
|
-
* sets the counts at all: `validatePlugin` writes `status` and `summary` but
|
|
2484
|
-
* not `issueCounts`) left the two disagreeing inside one document. A real
|
|
2485
|
-
* `vat audit --user` run said 55/422/504 in the header over per-file counts
|
|
2486
|
-
* summing to 55/360/405, with 91 of 614 entries declaring `{0,0,0}` above the
|
|
2487
|
-
* findings they listed. Re-deriving here means the header and the sum are the
|
|
2488
|
-
* same arithmetic on the same array, so they cannot drift again no matter what
|
|
2489
|
-
* a producer forgets.
|
|
2490
|
-
*
|
|
2491
|
-
* `linkedFiles[].issues` are deliberately NOT added: every linked finding is
|
|
2492
|
-
* also present in its owner's `issues`, so the nested list is a VIEW of records
|
|
2493
|
-
* already counted, not extra records. `audit-report-coherence.integration.test.ts`
|
|
2494
|
-
* pins that subset relation, because counting once is only correct while it holds.
|
|
2495
|
-
*
|
|
2496
|
-
* 🚨 **Zero files audited is an ERROR, not "an empty tree audits cleanly".**
|
|
2497
|
-
* `calculateOverallStatus([])` is `success`, so an existing directory holding
|
|
2498
|
-
* nothing auditable — moved plugins, a wrong subdirectory, an excluded tree, a
|
|
2499
|
-
* tree of files no lane recognises — published `status: success` beside
|
|
2500
|
-
* `filesScanned: 0`, and this command's own documentation tells CI to gate on
|
|
2501
|
-
* that `status`. Derived HERE, in the one builder both the directory lane
|
|
2502
|
-
* (`calculateSummary`) and the `--user` lane (`calculateHierarchicalSummary`)
|
|
2503
|
-
* pass through, so neither can publish a clean status over a zero denominator.
|
|
2504
|
-
* Through the shared mechanism in `run-integrity.ts`: one non-overridable
|
|
2505
|
-
* `RESOURCE_CHECK_BROKEN` at `error`, published under a top-level `issues` —
|
|
2506
|
-
* the claim is about the RUN, so it is not a `files[]` row and does not count
|
|
2507
|
-
* toward `filesScanned` — and counted in the header `issueCounts`, so the
|
|
2508
|
-
* identity becomes `issueCounts === Σ files[].issueCounts + Σ issues`.
|
|
2509
|
-
*
|
|
2510
|
-
* The exit code is NOT touched by this: `status` describes the findings and the
|
|
2511
|
-
* exit code describes whether the run completed, and this run completed. See
|
|
2512
|
-
* {@link createAuditCommand}.
|
|
2513
|
-
*/
|
|
2514
|
-
function buildBaseSummary(results, startTime) {
|
|
2515
|
-
const issueCounts = { errors: 0, warnings: 0, info: 0 };
|
|
2516
|
-
const entries = results.map((result) => {
|
|
2517
|
-
const counts = countBySeverity(result.issues);
|
|
2518
|
-
issueCounts.errors += counts.errors;
|
|
2519
|
-
issueCounts.warnings += counts.warnings;
|
|
2520
|
-
issueCounts.info += counts.info;
|
|
2521
|
-
return { ...result, issueCounts: counts };
|
|
2522
|
-
});
|
|
2523
|
-
const summary = countFilesByStatus(entries);
|
|
2524
|
-
// The denominator is files READ: a tree whose every path was refused audited
|
|
2525
|
-
// nothing, and says so through the same refusal as an empty tree.
|
|
2526
|
-
const runIssues = nothingCheckedFinding(summary.filesScanned, entries.flatMap((entry) => entry.issues), () => 'The audit ran over 0 files, so this report is not a verdict: a tree with nothing'
|
|
2527
|
-
+ ' to audit produces the same counts as a clean one. The path resolved to a tree'
|
|
2528
|
-
+ ' holding no auditable file — usually a wrong subdirectory, plugins or skills that'
|
|
2529
|
-
+ ' have moved, an excluded tree, files no audit lane recognises, or `--no-recursive`'
|
|
2530
|
-
+ ' over a tree whose resources sit deeper. Point the command at the plugin,'
|
|
2531
|
-
+ ' marketplace, registry or SKILL.md tree it should read.');
|
|
2532
|
-
return {
|
|
2533
|
-
entries,
|
|
2534
|
-
// Every run-integrity finding is `error` by construction (invariant 2 of
|
|
2535
|
-
// `run-integrity.ts`), so a non-empty refusal IS the status; otherwise the
|
|
2536
|
-
// files decide it, as before.
|
|
2537
|
-
status: runIssues.length > 0 ? 'error' : calculateOverallStatus(entries),
|
|
2538
|
-
summary,
|
|
2539
|
-
issueCounts: sumSeverityCounts([issueCounts, countBySeverity(runIssues)]),
|
|
2540
|
-
...(runIssues.length === 0 ? {} : { issues: [...runIssues] }),
|
|
2541
|
-
duration: `${Date.now() - startTime}ms`,
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
/**
|
|
2545
|
-
* Calculate summary for hierarchical output
|
|
2546
|
-
*/
|
|
2547
|
-
function calculateHierarchicalSummary(results, hierarchical, startTime, compatMap, verbose, root) {
|
|
2548
|
-
const { entries, ...base } = buildBaseSummary(results, startTime);
|
|
2549
|
-
const withCompat = applyCompatMap(entries, compatMap, root);
|
|
2550
|
-
return {
|
|
2551
|
-
root,
|
|
2552
|
-
...base,
|
|
2553
|
-
summary: {
|
|
2554
|
-
...base.summary,
|
|
2555
|
-
marketplaces: hierarchical.marketplaces.length,
|
|
2556
|
-
cachedPlugins: hierarchical.cachedPlugins.length,
|
|
2557
|
-
standalonePlugins: hierarchical.standalonePlugins.length,
|
|
2558
|
-
standaloneSkills: hierarchical.standaloneSkills.length,
|
|
2577
|
+
examined: scanned.length,
|
|
2578
|
+
counts: {
|
|
2579
|
+
filesPassed: scanned.length - withErrors - withWarnings,
|
|
2580
|
+
filesWithWarnings: withWarnings,
|
|
2581
|
+
filesWithErrors: withErrors,
|
|
2582
|
+
pathsUnreadable: results.length - scanned.length,
|
|
2559
2583
|
},
|
|
2560
|
-
files: relativizePathEntries(applyVerboseFilter(withCompat, verbose), root, NESTED_PATH_CARRIERS),
|
|
2561
|
-
hierarchical,
|
|
2562
2584
|
};
|
|
2563
2585
|
}
|
|
2564
2586
|
/**
|
|
2565
|
-
*
|
|
2587
|
+
* The human channel for the `--user` lane, read off the WRITTEN report. The
|
|
2588
|
+
* exit code is not decided here: the caller ends on `exitCodeForReport`.
|
|
2566
2589
|
*/
|
|
2567
|
-
function logHierarchicalSummary(results,
|
|
2568
|
-
const
|
|
2590
|
+
function logHierarchicalSummary({ results, written, data }, logger) {
|
|
2591
|
+
const { filesWithErrors, filesWithWarnings } = data.counts;
|
|
2569
2592
|
const skillsWithIssues = countResultsWithFindings(results);
|
|
2570
2593
|
const totalSkills = results.length;
|
|
2571
|
-
|
|
2572
|
-
const refused = logRunIntegrity(runIssues, logger);
|
|
2573
|
-
if (refused) {
|
|
2594
|
+
if (logRunIntegrity(written, logger)) {
|
|
2574
2595
|
// Rendered above; there is no skill verdict to print over zero skills.
|
|
2575
2596
|
}
|
|
2576
|
-
else if (
|
|
2577
|
-
|
|
2578
|
-
logger.error(`Audit found ${errorCount} skill(s) with errors (${totalSkills} scanned, ${skillsWithIssues} with issues)`);
|
|
2597
|
+
else if (filesWithErrors > 0) {
|
|
2598
|
+
logger.error(`Audit found ${filesWithErrors} skill(s) with errors (${totalSkills} scanned, ${skillsWithIssues} with issues)`);
|
|
2579
2599
|
}
|
|
2580
|
-
else if (
|
|
2581
|
-
|
|
2582
|
-
logger.info(`Audit passed with warnings: ${warningCount} skill(s) (${totalSkills} scanned, ${skillsWithIssues} with issues)`);
|
|
2600
|
+
else if (filesWithWarnings > 0) {
|
|
2601
|
+
logger.info(`Audit passed with warnings: ${filesWithWarnings} skill(s) (${totalSkills} scanned, ${skillsWithIssues} with issues)`);
|
|
2583
2602
|
}
|
|
2584
2603
|
else if (skillsWithIssues > 0) {
|
|
2585
|
-
//
|
|
2586
|
-
//
|
|
2604
|
+
// Nothing actionable is NOT "nothing to see". Saying only "N passed" over
|
|
2605
|
+
// a pile of info findings is how they stayed invisible.
|
|
2587
2606
|
logger.info(`Audit successful: ${totalSkills} skill(s) passed (${skillsWithIssues} with informational findings)`);
|
|
2588
2607
|
}
|
|
2589
2608
|
else {
|
|
2590
2609
|
logger.info(`Audit successful: ${totalSkills} skill(s) passed`);
|
|
2591
2610
|
}
|
|
2592
2611
|
renderAuditFooter(results, logger);
|
|
2593
|
-
process.exit(refused || status === 'error' ? ExitCode.FINDINGS : ExitCode.OK);
|
|
2594
2612
|
}
|
|
2595
2613
|
//# sourceMappingURL=audit.js.map
|