@opensip-tools/fitness 1.0.4
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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE +21 -0
- package/dist/__tests__/gate.test.d.ts +13 -0
- package/dist/__tests__/gate.test.d.ts.map +1 -0
- package/dist/__tests__/gate.test.js +422 -0
- package/dist/__tests__/gate.test.js.map +1 -0
- package/dist/__tests__/sarif.test.d.ts +2 -0
- package/dist/__tests__/sarif.test.d.ts.map +1 -0
- package/dist/__tests__/sarif.test.js +169 -0
- package/dist/__tests__/sarif.test.js.map +1 -0
- package/dist/cli/dashboard.d.ts +6 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +77 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/fit.d.ts +37 -0
- package/dist/cli/fit.d.ts.map +1 -0
- package/dist/cli/fit.js +539 -0
- package/dist/cli/fit.js.map +1 -0
- package/dist/cli/list-checks.d.ts +6 -0
- package/dist/cli/list-checks.d.ts.map +1 -0
- package/dist/cli/list-checks.js +23 -0
- package/dist/cli/list-checks.js.map +1 -0
- package/dist/cli/list-recipes.d.ts +6 -0
- package/dist/cli/list-recipes.d.ts.map +1 -0
- package/dist/cli/list-recipes.js +31 -0
- package/dist/cli/list-recipes.js.map +1 -0
- package/dist/framework/__tests__/ast-utilities.test.d.ts +2 -0
- package/dist/framework/__tests__/ast-utilities.test.d.ts.map +1 -0
- package/dist/framework/__tests__/ast-utilities.test.js +153 -0
- package/dist/framework/__tests__/ast-utilities.test.js.map +1 -0
- package/dist/framework/__tests__/check-config.test.d.ts +2 -0
- package/dist/framework/__tests__/check-config.test.d.ts.map +1 -0
- package/dist/framework/__tests__/check-config.test.js +56 -0
- package/dist/framework/__tests__/check-config.test.js.map +1 -0
- package/dist/framework/__tests__/command-executor.test.d.ts +2 -0
- package/dist/framework/__tests__/command-executor.test.d.ts.map +1 -0
- package/dist/framework/__tests__/command-executor.test.js +71 -0
- package/dist/framework/__tests__/command-executor.test.js.map +1 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.d.ts +2 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.d.ts.map +1 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.js +104 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.js.map +1 -0
- package/dist/framework/__tests__/content-filter.test.d.ts +2 -0
- package/dist/framework/__tests__/content-filter.test.d.ts.map +1 -0
- package/dist/framework/__tests__/content-filter.test.js +126 -0
- package/dist/framework/__tests__/content-filter.test.js.map +1 -0
- package/dist/framework/__tests__/define-check.test.d.ts +2 -0
- package/dist/framework/__tests__/define-check.test.d.ts.map +1 -0
- package/dist/framework/__tests__/define-check.test.js +155 -0
- package/dist/framework/__tests__/define-check.test.js.map +1 -0
- package/dist/framework/__tests__/directive-inventory.test.d.ts +2 -0
- package/dist/framework/__tests__/directive-inventory.test.d.ts.map +1 -0
- package/dist/framework/__tests__/directive-inventory.test.js +44 -0
- package/dist/framework/__tests__/directive-inventory.test.js.map +1 -0
- package/dist/framework/__tests__/execution-context.test.d.ts +2 -0
- package/dist/framework/__tests__/execution-context.test.d.ts.map +1 -0
- package/dist/framework/__tests__/execution-context.test.js +62 -0
- package/dist/framework/__tests__/execution-context.test.js.map +1 -0
- package/dist/framework/__tests__/file-accessor.test.d.ts +2 -0
- package/dist/framework/__tests__/file-accessor.test.d.ts.map +1 -0
- package/dist/framework/__tests__/file-accessor.test.js +106 -0
- package/dist/framework/__tests__/file-accessor.test.js.map +1 -0
- package/dist/framework/__tests__/file-cache.test.d.ts +2 -0
- package/dist/framework/__tests__/file-cache.test.d.ts.map +1 -0
- package/dist/framework/__tests__/file-cache.test.js +122 -0
- package/dist/framework/__tests__/file-cache.test.js.map +1 -0
- package/dist/framework/__tests__/import-graph.test.d.ts +15 -0
- package/dist/framework/__tests__/import-graph.test.d.ts.map +1 -0
- package/dist/framework/__tests__/import-graph.test.js +164 -0
- package/dist/framework/__tests__/import-graph.test.js.map +1 -0
- package/dist/framework/__tests__/path-matcher.test.d.ts +2 -0
- package/dist/framework/__tests__/path-matcher.test.d.ts.map +1 -0
- package/dist/framework/__tests__/path-matcher.test.js +113 -0
- package/dist/framework/__tests__/path-matcher.test.js.map +1 -0
- package/dist/framework/__tests__/register-helpers.test.d.ts +2 -0
- package/dist/framework/__tests__/register-helpers.test.d.ts.map +1 -0
- package/dist/framework/__tests__/register-helpers.test.js +42 -0
- package/dist/framework/__tests__/register-helpers.test.js.map +1 -0
- package/dist/framework/__tests__/registry.test.d.ts +2 -0
- package/dist/framework/__tests__/registry.test.d.ts.map +1 -0
- package/dist/framework/__tests__/registry.test.js +208 -0
- package/dist/framework/__tests__/registry.test.js.map +1 -0
- package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
- package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
- package/dist/framework/__tests__/result-builder.test.js +153 -0
- package/dist/framework/__tests__/result-builder.test.js.map +1 -0
- package/dist/framework/__tests__/scope-resolver.test.d.ts +2 -0
- package/dist/framework/__tests__/scope-resolver.test.d.ts.map +1 -0
- package/dist/framework/__tests__/scope-resolver.test.js +140 -0
- package/dist/framework/__tests__/scope-resolver.test.js.map +1 -0
- package/dist/framework/__tests__/severity-mapping.test.d.ts +2 -0
- package/dist/framework/__tests__/severity-mapping.test.d.ts.map +1 -0
- package/dist/framework/__tests__/severity-mapping.test.js +42 -0
- package/dist/framework/__tests__/severity-mapping.test.js.map +1 -0
- package/dist/framework/__tests__/strip-literals.test.d.ts +2 -0
- package/dist/framework/__tests__/strip-literals.test.d.ts.map +1 -0
- package/dist/framework/__tests__/strip-literals.test.js +87 -0
- package/dist/framework/__tests__/strip-literals.test.js.map +1 -0
- package/dist/framework/abortable-exec.d.ts +34 -0
- package/dist/framework/abortable-exec.d.ts.map +1 -0
- package/dist/framework/abortable-exec.js +136 -0
- package/dist/framework/abortable-exec.js.map +1 -0
- package/dist/framework/ast-utilities.d.ts +41 -0
- package/dist/framework/ast-utilities.d.ts.map +1 -0
- package/dist/framework/ast-utilities.js +106 -0
- package/dist/framework/ast-utilities.js.map +1 -0
- package/dist/framework/check-config.d.ts +171 -0
- package/dist/framework/check-config.d.ts.map +1 -0
- package/dist/framework/check-config.js +114 -0
- package/dist/framework/check-config.js.map +1 -0
- package/dist/framework/check-types.d.ts +57 -0
- package/dist/framework/check-types.d.ts.map +1 -0
- package/dist/framework/check-types.js +35 -0
- package/dist/framework/check-types.js.map +1 -0
- package/dist/framework/command-executor.d.ts +25 -0
- package/dist/framework/command-executor.d.ts.map +1 -0
- package/dist/framework/command-executor.js +63 -0
- package/dist/framework/command-executor.js.map +1 -0
- package/dist/framework/constants.d.ts +9 -0
- package/dist/framework/constants.d.ts.map +1 -0
- package/dist/framework/constants.js +16 -0
- package/dist/framework/constants.js.map +1 -0
- package/dist/framework/content-filter.d.ts +33 -0
- package/dist/framework/content-filter.d.ts.map +1 -0
- package/dist/framework/content-filter.js +236 -0
- package/dist/framework/content-filter.js.map +1 -0
- package/dist/framework/define-check.d.ts +38 -0
- package/dist/framework/define-check.d.ts.map +1 -0
- package/dist/framework/define-check.js +252 -0
- package/dist/framework/define-check.js.map +1 -0
- package/dist/framework/directive-inventory.d.ts +34 -0
- package/dist/framework/directive-inventory.d.ts.map +1 -0
- package/dist/framework/directive-inventory.js +77 -0
- package/dist/framework/directive-inventory.js.map +1 -0
- package/dist/framework/directive-parsing.d.ts +20 -0
- package/dist/framework/directive-parsing.d.ts.map +1 -0
- package/dist/framework/directive-parsing.js +121 -0
- package/dist/framework/directive-parsing.js.map +1 -0
- package/dist/framework/execution-context.d.ts +95 -0
- package/dist/framework/execution-context.d.ts.map +1 -0
- package/dist/framework/execution-context.js +122 -0
- package/dist/framework/execution-context.js.map +1 -0
- package/dist/framework/file-accessor.d.ts +20 -0
- package/dist/framework/file-accessor.d.ts.map +1 -0
- package/dist/framework/file-accessor.js +122 -0
- package/dist/framework/file-accessor.js.map +1 -0
- package/dist/framework/file-cache.d.ts +70 -0
- package/dist/framework/file-cache.d.ts.map +1 -0
- package/dist/framework/file-cache.js +178 -0
- package/dist/framework/file-cache.js.map +1 -0
- package/dist/framework/file-type-filter.d.ts +11 -0
- package/dist/framework/file-type-filter.d.ts.map +1 -0
- package/dist/framework/file-type-filter.js +21 -0
- package/dist/framework/file-type-filter.js.map +1 -0
- package/dist/framework/ignore-processing.d.ts +22 -0
- package/dist/framework/ignore-processing.d.ts.map +1 -0
- package/dist/framework/ignore-processing.js +241 -0
- package/dist/framework/ignore-processing.js.map +1 -0
- package/dist/framework/import-graph.d.ts +51 -0
- package/dist/framework/import-graph.d.ts.map +1 -0
- package/dist/framework/import-graph.js +216 -0
- package/dist/framework/import-graph.js.map +1 -0
- package/dist/framework/memory-profiler.d.ts +53 -0
- package/dist/framework/memory-profiler.d.ts.map +1 -0
- package/dist/framework/memory-profiler.js +92 -0
- package/dist/framework/memory-profiler.js.map +1 -0
- package/dist/framework/parse-cache.d.ts +23 -0
- package/dist/framework/parse-cache.d.ts.map +1 -0
- package/dist/framework/parse-cache.js +37 -0
- package/dist/framework/parse-cache.js.map +1 -0
- package/dist/framework/path-matcher.d.ts +86 -0
- package/dist/framework/path-matcher.d.ts.map +1 -0
- package/dist/framework/path-matcher.js +138 -0
- package/dist/framework/path-matcher.js.map +1 -0
- package/dist/framework/register-helpers.d.ts +10 -0
- package/dist/framework/register-helpers.d.ts.map +1 -0
- package/dist/framework/register-helpers.js +17 -0
- package/dist/framework/register-helpers.js.map +1 -0
- package/dist/framework/registry.d.ts +41 -0
- package/dist/framework/registry.d.ts.map +1 -0
- package/dist/framework/registry.js +103 -0
- package/dist/framework/registry.js.map +1 -0
- package/dist/framework/result-builder.d.ts +74 -0
- package/dist/framework/result-builder.d.ts.map +1 -0
- package/dist/framework/result-builder.js +154 -0
- package/dist/framework/result-builder.js.map +1 -0
- package/dist/framework/scope-resolver.d.ts +23 -0
- package/dist/framework/scope-resolver.d.ts.map +1 -0
- package/dist/framework/scope-resolver.js +201 -0
- package/dist/framework/scope-resolver.js.map +1 -0
- package/dist/framework/severity-mapping.d.ts +13 -0
- package/dist/framework/severity-mapping.d.ts.map +1 -0
- package/dist/framework/severity-mapping.js +51 -0
- package/dist/framework/severity-mapping.js.map +1 -0
- package/dist/framework/strip-literals.d.ts +48 -0
- package/dist/framework/strip-literals.d.ts.map +1 -0
- package/dist/framework/strip-literals.js +188 -0
- package/dist/framework/strip-literals.js.map +1 -0
- package/dist/gate.d.ts +74 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +257 -0
- package/dist/gate.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/__tests__/check-package-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/check-package-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/check-package-discovery.test.js +170 -0
- package/dist/plugins/__tests__/check-package-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/lang-domain.test.d.ts +2 -0
- package/dist/plugins/__tests__/lang-domain.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/lang-domain.test.js +171 -0
- package/dist/plugins/__tests__/lang-domain.test.js.map +1 -0
- package/dist/plugins/__tests__/loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/loader.test.js +194 -0
- package/dist/plugins/__tests__/loader.test.js.map +1 -0
- package/dist/plugins/check-package-discovery.d.ts +73 -0
- package/dist/plugins/check-package-discovery.d.ts.map +1 -0
- package/dist/plugins/check-package-discovery.js +212 -0
- package/dist/plugins/check-package-discovery.js.map +1 -0
- package/dist/plugins/loader.d.ts +31 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +290 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.d.ts +23 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +9 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/recipes/__tests__/built-in-recipes.test.d.ts +2 -0
- package/dist/recipes/__tests__/built-in-recipes.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/built-in-recipes.test.js +93 -0
- package/dist/recipes/__tests__/built-in-recipes.test.js.map +1 -0
- package/dist/recipes/__tests__/check-config.test.d.ts +5 -0
- package/dist/recipes/__tests__/check-config.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/check-config.test.js +37 -0
- package/dist/recipes/__tests__/check-config.test.js.map +1 -0
- package/dist/recipes/__tests__/check-resolution.test.d.ts +2 -0
- package/dist/recipes/__tests__/check-resolution.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/check-resolution.test.js +135 -0
- package/dist/recipes/__tests__/check-resolution.test.js.map +1 -0
- package/dist/recipes/__tests__/registry.test.d.ts +2 -0
- package/dist/recipes/__tests__/registry.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/registry.test.js +97 -0
- package/dist/recipes/__tests__/registry.test.js.map +1 -0
- package/dist/recipes/__tests__/retry.test.d.ts +2 -0
- package/dist/recipes/__tests__/retry.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/retry.test.js +75 -0
- package/dist/recipes/__tests__/retry.test.js.map +1 -0
- package/dist/recipes/__tests__/service.test.d.ts +11 -0
- package/dist/recipes/__tests__/service.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/service.test.js +482 -0
- package/dist/recipes/__tests__/service.test.js.map +1 -0
- package/dist/recipes/built-in-recipes.d.ts +14 -0
- package/dist/recipes/built-in-recipes.d.ts.map +1 -0
- package/dist/recipes/built-in-recipes.js +247 -0
- package/dist/recipes/built-in-recipes.js.map +1 -0
- package/dist/recipes/check-config.d.ts +40 -0
- package/dist/recipes/check-config.d.ts.map +1 -0
- package/dist/recipes/check-config.js +61 -0
- package/dist/recipes/check-config.js.map +1 -0
- package/dist/recipes/check-resolution.d.ts +21 -0
- package/dist/recipes/check-resolution.d.ts.map +1 -0
- package/dist/recipes/check-resolution.js +121 -0
- package/dist/recipes/check-resolution.js.map +1 -0
- package/dist/recipes/check-result-processor.d.ts +51 -0
- package/dist/recipes/check-result-processor.d.ts.map +1 -0
- package/dist/recipes/check-result-processor.js +158 -0
- package/dist/recipes/check-result-processor.js.map +1 -0
- package/dist/recipes/parallel-execution.d.ts +33 -0
- package/dist/recipes/parallel-execution.d.ts.map +1 -0
- package/dist/recipes/parallel-execution.js +142 -0
- package/dist/recipes/parallel-execution.js.map +1 -0
- package/dist/recipes/registry.d.ts +81 -0
- package/dist/recipes/registry.d.ts.map +1 -0
- package/dist/recipes/registry.js +131 -0
- package/dist/recipes/registry.js.map +1 -0
- package/dist/recipes/retry.d.ts +25 -0
- package/dist/recipes/retry.d.ts.map +1 -0
- package/dist/recipes/retry.js +44 -0
- package/dist/recipes/retry.js.map +1 -0
- package/dist/recipes/sequential-execution.d.ts +10 -0
- package/dist/recipes/sequential-execution.d.ts.map +1 -0
- package/dist/recipes/sequential-execution.js +122 -0
- package/dist/recipes/sequential-execution.js.map +1 -0
- package/dist/recipes/service-types.d.ts +84 -0
- package/dist/recipes/service-types.d.ts.map +1 -0
- package/dist/recipes/service-types.js +8 -0
- package/dist/recipes/service-types.js.map +1 -0
- package/dist/recipes/service.d.ts +71 -0
- package/dist/recipes/service.d.ts.map +1 -0
- package/dist/recipes/service.js +331 -0
- package/dist/recipes/service.js.map +1 -0
- package/dist/recipes/types.d.ts +154 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +54 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/sarif.d.ts +34 -0
- package/dist/sarif.d.ts.map +1 -0
- package/dist/sarif.js +192 -0
- package/dist/sarif.js.map +1 -0
- package/dist/signalers/__tests__/loader.test.d.ts +2 -0
- package/dist/signalers/__tests__/loader.test.d.ts.map +1 -0
- package/dist/signalers/__tests__/loader.test.js +74 -0
- package/dist/signalers/__tests__/loader.test.js.map +1 -0
- package/dist/signalers/index.d.ts +8 -0
- package/dist/signalers/index.d.ts.map +1 -0
- package/dist/signalers/index.js +9 -0
- package/dist/signalers/index.js.map +1 -0
- package/dist/signalers/loader.d.ts +24 -0
- package/dist/signalers/loader.d.ts.map +1 -0
- package/dist/signalers/loader.js +108 -0
- package/dist/signalers/loader.js.map +1 -0
- package/dist/signalers/schema.d.ts +288 -0
- package/dist/signalers/schema.d.ts.map +1 -0
- package/dist/signalers/schema.js +99 -0
- package/dist/signalers/schema.js.map +1 -0
- package/dist/signalers/types.d.ts +13 -0
- package/dist/signalers/types.d.ts.map +1 -0
- package/dist/signalers/types.js +5 -0
- package/dist/signalers/types.js.map +1 -0
- package/dist/targets/__tests__/loader.test.d.ts +2 -0
- package/dist/targets/__tests__/loader.test.d.ts.map +1 -0
- package/dist/targets/__tests__/loader.test.js +127 -0
- package/dist/targets/__tests__/loader.test.js.map +1 -0
- package/dist/targets/__tests__/resolver.test.d.ts +2 -0
- package/dist/targets/__tests__/resolver.test.d.ts.map +1 -0
- package/dist/targets/__tests__/resolver.test.js +54 -0
- package/dist/targets/__tests__/resolver.test.js.map +1 -0
- package/dist/targets/__tests__/target-registry.test.d.ts +2 -0
- package/dist/targets/__tests__/target-registry.test.d.ts.map +1 -0
- package/dist/targets/__tests__/target-registry.test.js +89 -0
- package/dist/targets/__tests__/target-registry.test.js.map +1 -0
- package/dist/targets/index.d.ts +10 -0
- package/dist/targets/index.d.ts.map +1 -0
- package/dist/targets/index.js +12 -0
- package/dist/targets/index.js.map +1 -0
- package/dist/targets/loader.d.ts +19 -0
- package/dist/targets/loader.d.ts.map +1 -0
- package/dist/targets/loader.js +159 -0
- package/dist/targets/loader.js.map +1 -0
- package/dist/targets/resolver.d.ts +19 -0
- package/dist/targets/resolver.d.ts.map +1 -0
- package/dist/targets/resolver.js +37 -0
- package/dist/targets/resolver.js.map +1 -0
- package/dist/targets/target-registry.d.ts +61 -0
- package/dist/targets/target-registry.d.ts.map +1 -0
- package/dist/targets/target-registry.js +93 -0
- package/dist/targets/target-registry.js.map +1 -0
- package/dist/targets/types.d.ts +85 -0
- package/dist/targets/types.d.ts.map +1 -0
- package/dist/targets/types.js +5 -0
- package/dist/targets/types.js.map +1 -0
- package/dist/tool.d.ts +17 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +282 -0
- package/dist/tool.js.map +1 -0
- package/dist/types/findings.d.ts +117 -0
- package/dist/types/findings.d.ts.map +1 -0
- package/dist/types/findings.js +93 -0
- package/dist/types/findings.js.map +1 -0
- package/dist/types/severity.d.ts +15 -0
- package/dist/types/severity.d.ts.map +1 -0
- package/dist/types/severity.js +36 -0
- package/dist/types/severity.js.map +1 -0
- package/package.json +45 -0
- package/src/__tests__/gate.test.ts +537 -0
- package/src/__tests__/sarif.test.ts +201 -0
- package/src/cli/dashboard.ts +93 -0
- package/src/cli/fit.ts +612 -0
- package/src/cli/list-checks.ts +32 -0
- package/src/cli/list-recipes.ts +38 -0
- package/src/framework/__tests__/ast-utilities.test.ts +157 -0
- package/src/framework/__tests__/check-config.test.ts +65 -0
- package/src/framework/__tests__/command-executor.test.ts +79 -0
- package/src/framework/__tests__/content-filter-dispatch.test.ts +132 -0
- package/src/framework/__tests__/content-filter.test.ts +136 -0
- package/src/framework/__tests__/define-check.test.ts +180 -0
- package/src/framework/__tests__/directive-inventory.test.ts +53 -0
- package/src/framework/__tests__/execution-context.test.ts +80 -0
- package/src/framework/__tests__/file-accessor.test.ts +121 -0
- package/src/framework/__tests__/file-cache.test.ts +142 -0
- package/src/framework/__tests__/import-graph.test.ts +282 -0
- package/src/framework/__tests__/path-matcher.test.ts +130 -0
- package/src/framework/__tests__/register-helpers.test.ts +51 -0
- package/src/framework/__tests__/registry.test.ts +243 -0
- package/src/framework/__tests__/result-builder.test.ts +178 -0
- package/src/framework/__tests__/scope-resolver.test.ts +208 -0
- package/src/framework/__tests__/severity-mapping.test.ts +50 -0
- package/src/framework/__tests__/strip-literals.test.ts +109 -0
- package/src/framework/abortable-exec.ts +177 -0
- package/src/framework/ast-utilities.ts +112 -0
- package/src/framework/check-config.ts +339 -0
- package/src/framework/check-types.ts +77 -0
- package/src/framework/command-executor.ts +100 -0
- package/src/framework/constants.ts +16 -0
- package/src/framework/content-filter.ts +288 -0
- package/src/framework/define-check.ts +336 -0
- package/src/framework/directive-inventory.ts +110 -0
- package/src/framework/directive-parsing.ts +152 -0
- package/src/framework/execution-context.ts +247 -0
- package/src/framework/file-accessor.ts +171 -0
- package/src/framework/file-cache.ts +220 -0
- package/src/framework/file-type-filter.ts +25 -0
- package/src/framework/ignore-processing.ts +350 -0
- package/src/framework/import-graph.ts +280 -0
- package/src/framework/memory-profiler.ts +145 -0
- package/src/framework/parse-cache.ts +38 -0
- package/src/framework/path-matcher.ts +191 -0
- package/src/framework/register-helpers.ts +20 -0
- package/src/framework/registry.ts +125 -0
- package/src/framework/result-builder.ts +225 -0
- package/src/framework/scope-resolver.ts +262 -0
- package/src/framework/severity-mapping.ts +56 -0
- package/src/framework/strip-literals.ts +200 -0
- package/src/gate.ts +337 -0
- package/src/index.ts +110 -0
- package/src/plugins/__tests__/check-package-discovery.test.ts +204 -0
- package/src/plugins/__tests__/lang-domain.test.ts +198 -0
- package/src/plugins/__tests__/loader.test.ts +226 -0
- package/src/plugins/check-package-discovery.ts +242 -0
- package/src/plugins/loader.ts +327 -0
- package/src/plugins/types.ts +25 -0
- package/src/recipes/__tests__/built-in-recipes.test.ts +107 -0
- package/src/recipes/__tests__/check-config.test.ts +51 -0
- package/src/recipes/__tests__/check-resolution.test.ts +185 -0
- package/src/recipes/__tests__/registry.test.ts +115 -0
- package/src/recipes/__tests__/retry.test.ts +83 -0
- package/src/recipes/__tests__/service.test.ts +572 -0
- package/src/recipes/built-in-recipes.ts +273 -0
- package/src/recipes/check-config.ts +64 -0
- package/src/recipes/check-resolution.ts +169 -0
- package/src/recipes/check-result-processor.ts +258 -0
- package/src/recipes/parallel-execution.ts +220 -0
- package/src/recipes/registry.ts +192 -0
- package/src/recipes/retry.ts +69 -0
- package/src/recipes/sequential-execution.ts +139 -0
- package/src/recipes/service-types.ts +105 -0
- package/src/recipes/service.ts +400 -0
- package/src/recipes/types.ts +247 -0
- package/src/sarif.ts +232 -0
- package/src/signalers/__tests__/loader.test.ts +99 -0
- package/src/signalers/index.ts +9 -0
- package/src/signalers/loader.ts +141 -0
- package/src/signalers/schema.ts +117 -0
- package/src/signalers/types.ts +15 -0
- package/src/targets/__tests__/loader.test.ts +170 -0
- package/src/targets/__tests__/resolver.test.ts +74 -0
- package/src/targets/__tests__/target-registry.test.ts +103 -0
- package/src/targets/index.ts +13 -0
- package/src/targets/loader.ts +214 -0
- package/src/targets/resolver.ts +44 -0
- package/src/targets/target-registry.ts +111 -0
- package/src/targets/types.ts +89 -0
- package/src/tool.ts +302 -0
- package/src/types/findings.ts +239 -0
- package/src/types/severity.ts +39 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +33 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Target Registry
|
|
3
|
+
*
|
|
4
|
+
* Registry for target definitions. Provides lookup by name and tags.
|
|
5
|
+
* Standalone implementation without platform GenericRegistry dependency.
|
|
6
|
+
*
|
|
7
|
+
* The entire targets module uses a synchronous API because target definitions
|
|
8
|
+
* are loaded once at startup from a small YAML config file (via loader.ts) and
|
|
9
|
+
* then held in-memory for fast, repeated lookups throughout the process lifetime.
|
|
10
|
+
* The resolver (resolver.ts) similarly uses synchronous glob expansion. Since the
|
|
11
|
+
* data set is small and bounded by project configuration, async I/O offers no
|
|
12
|
+
* practical benefit and would complicate every call site that queries targets.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { Target } from './types.js'
|
|
16
|
+
|
|
17
|
+
/** Registry for target definitions with lookup by name and tags. */
|
|
18
|
+
export class TargetRegistry {
|
|
19
|
+
private readonly targets = new Map<string, Target>()
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Register a target. Silently skips if a target with the same name already exists.
|
|
23
|
+
* @param target - Target definition to register
|
|
24
|
+
* @returns This registry instance for chaining
|
|
25
|
+
*/
|
|
26
|
+
register(target: Target): this {
|
|
27
|
+
const name = target.config.name
|
|
28
|
+
|
|
29
|
+
if (this.targets.has(name)) {
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.targets.set(name, target)
|
|
34
|
+
return this
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Look up a target by its config name.
|
|
39
|
+
* @param name - Target name to find
|
|
40
|
+
* @returns The matching target, or undefined if not found
|
|
41
|
+
*/
|
|
42
|
+
getByName(name: string): Target | undefined {
|
|
43
|
+
return this.targets.get(name)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Return all registered targets. */
|
|
47
|
+
getAll(): readonly Target[] {
|
|
48
|
+
return [...this.targets.values()]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Return all targets that include the given tag.
|
|
53
|
+
* @param tag - Tag string to filter by
|
|
54
|
+
* @returns Targets whose config.tags contain the tag
|
|
55
|
+
*/
|
|
56
|
+
getByTag(tag: string): readonly Target[] {
|
|
57
|
+
return this.getAll().filter((t) => t.config.tags?.includes(tag))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check whether a target with the given name is registered.
|
|
62
|
+
* @param name - Target name to check
|
|
63
|
+
* @returns True if the target exists in the registry
|
|
64
|
+
*/
|
|
65
|
+
has(name: string): boolean {
|
|
66
|
+
return this.targets.has(name)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Find targets whose languages and concerns intersect with the given scope.
|
|
71
|
+
*
|
|
72
|
+
* Both dimensions must match (AND logic):
|
|
73
|
+
* - A target matches languages if the intersection is non-empty (or either side is empty/undefined)
|
|
74
|
+
* - A target matches concerns if the intersection is non-empty (or either side is empty/undefined)
|
|
75
|
+
*
|
|
76
|
+
* @param languages - Languages the check is designed for
|
|
77
|
+
* @param concerns - Semantic concerns the check targets
|
|
78
|
+
* @returns Targets that match both dimensions
|
|
79
|
+
*/
|
|
80
|
+
findByScope(languages: readonly string[], concerns: readonly string[]): readonly Target[] {
|
|
81
|
+
return this.getAll().filter((target) => {
|
|
82
|
+
const targetLangs = target.config.languages
|
|
83
|
+
const targetConcerns = target.config.concerns
|
|
84
|
+
|
|
85
|
+
// Language matching: if either side has no languages, treat as "matches any"
|
|
86
|
+
const languageMatch =
|
|
87
|
+
languages.length === 0 ||
|
|
88
|
+
!targetLangs || targetLangs.length === 0 ||
|
|
89
|
+
languages.some((lang) => targetLangs.includes(lang))
|
|
90
|
+
|
|
91
|
+
// Concern matching: if either side has no concerns, treat as "matches any"
|
|
92
|
+
const concernMatch =
|
|
93
|
+
concerns.length === 0 ||
|
|
94
|
+
!targetConcerns || targetConcerns.length === 0 ||
|
|
95
|
+
concerns.some((concern) => targetConcerns.includes(concern))
|
|
96
|
+
|
|
97
|
+
return languageMatch && concernMatch
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Number of registered targets. */
|
|
102
|
+
get size(): number {
|
|
103
|
+
return this.targets.size
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Remove all targets from the registry. */
|
|
107
|
+
clear(): void {
|
|
108
|
+
this.targets.clear()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Target type definitions for shared targeting
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Configuration for a named target (file set with include/exclude globs). */
|
|
6
|
+
export interface TargetConfig {
|
|
7
|
+
/** Kebab-case identifier, e.g. 'backend', 'module-foundation' */
|
|
8
|
+
readonly name: string
|
|
9
|
+
/** Human-readable description */
|
|
10
|
+
readonly description: string
|
|
11
|
+
/** Glob patterns to include */
|
|
12
|
+
readonly include: readonly string[]
|
|
13
|
+
/** Glob patterns to exclude */
|
|
14
|
+
readonly exclude: readonly string[]
|
|
15
|
+
/** Context doc paths for assessments */
|
|
16
|
+
readonly context?: readonly string[]
|
|
17
|
+
/** Tags for filtering/grouping */
|
|
18
|
+
readonly tags?: readonly string[]
|
|
19
|
+
/** Languages this target contains (e.g. 'typescript', 'tsx', 'json') */
|
|
20
|
+
readonly languages?: readonly string[]
|
|
21
|
+
/** Semantic concerns this target represents (e.g. 'backend', 'server', 'api') */
|
|
22
|
+
readonly concerns?: readonly string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A resolved target wrapping its configuration. */
|
|
26
|
+
export interface Target {
|
|
27
|
+
readonly config: TargetConfig
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Per-check target overrides.
|
|
32
|
+
* Maps check slug → target name(s) to restrict which files a check runs against.
|
|
33
|
+
*/
|
|
34
|
+
type CheckTargetMap = Readonly<Record<string, string | readonly string[]>>
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Project-local plugin declarations — one list per plugin domain.
|
|
38
|
+
*
|
|
39
|
+
* When present in the config file, these override the default user-level
|
|
40
|
+
* plugin directory (`~/.opensip-tools/<domain>/`). Plugins get installed
|
|
41
|
+
* into `<project-root>/.opensip-tools/<domain>/` and are version-pinned
|
|
42
|
+
* by the project rather than by each developer's machine.
|
|
43
|
+
*
|
|
44
|
+
* Each entry is any npm install spec: `@scope/pkg`, `@scope/pkg@^1.2.3`,
|
|
45
|
+
* `./local-path`, `/abs/path/to/pkg.tgz`, `git+https://...`, etc.
|
|
46
|
+
*/
|
|
47
|
+
interface PluginsConfig {
|
|
48
|
+
readonly fit?: readonly string[]
|
|
49
|
+
readonly sim?: readonly string[]
|
|
50
|
+
readonly asm?: readonly string[]
|
|
51
|
+
readonly lang?: readonly string[]
|
|
52
|
+
/**
|
|
53
|
+
* Explicit list of npm package names to load as check providers
|
|
54
|
+
* (e.g. ['@opensip-tools/checks-python', '@my-org/checks-internal']).
|
|
55
|
+
*
|
|
56
|
+
* When present, ONLY these packages are loaded. Auto-discovery is
|
|
57
|
+
* disabled for the run. No package is privileged: if you want the
|
|
58
|
+
* default check pack you must list `@opensip-tools/checks-builtin`
|
|
59
|
+
* (or its successors) here explicitly. An empty list disables all
|
|
60
|
+
* check loading and triggers a no-checks-loaded warning.
|
|
61
|
+
*/
|
|
62
|
+
readonly checkPackages?: readonly string[]
|
|
63
|
+
/**
|
|
64
|
+
* When false, the CLI does NOT scan node_modules for
|
|
65
|
+
* @opensip-tools/checks-* packages. Default: true.
|
|
66
|
+
* Ignored when `checkPackages` is set (explicit list always wins).
|
|
67
|
+
*/
|
|
68
|
+
readonly autoDiscoverChecks?: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Result of loading targets config, including both the target registry
|
|
73
|
+
* and per-check target overrides.
|
|
74
|
+
*/
|
|
75
|
+
export interface TargetsConfig {
|
|
76
|
+
/** Global file exclusion patterns (replaces .fitnessignore). */
|
|
77
|
+
readonly globalExcludes: readonly string[]
|
|
78
|
+
/** Per-check target overrides for third-party/marketplace checks. */
|
|
79
|
+
readonly checkOverrides: CheckTargetMap
|
|
80
|
+
/**
|
|
81
|
+
* Project-local plugin declarations, keyed by domain. When any domain
|
|
82
|
+
* has entries here, plugin discovery for that domain reads from
|
|
83
|
+
* `<project>/.opensip-tools/<domain>/` instead of `~/.opensip-tools/<domain>/`.
|
|
84
|
+
* Absent (or undefined per-domain) = fall back to the user-level dir
|
|
85
|
+
* for that domain.
|
|
86
|
+
*/
|
|
87
|
+
readonly plugins?: PluginsConfig
|
|
88
|
+
}
|
|
89
|
+
|
package/src/tool.ts
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fitnessTool — fitness as a Tool plugin.
|
|
3
|
+
*
|
|
4
|
+
* Owns its full Commander wiring for the `fit`, `dashboard`, `fit-list`,
|
|
5
|
+
* and `fit-recipes` subcommands. The CLI calls register() once at
|
|
6
|
+
* startup and the rest is local: every option-parsing rule, gate-mode
|
|
7
|
+
* dispatch, JSON-vs-Ink rendering decision, and dashboard auto-open
|
|
8
|
+
* lives here, in the package that owns the fitness command surface.
|
|
9
|
+
*
|
|
10
|
+
* The CLI no longer imports `executeFit`, `openDashboard`, etc.
|
|
11
|
+
* directly — it just calls `fitnessTool.register(cli)`. Adding a new
|
|
12
|
+
* subcommand to fitness is a local change; no CLI edit required.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import { EXIT_CODES } from '@opensip-tools/contracts';
|
|
17
|
+
import { type Command } from 'commander';
|
|
18
|
+
|
|
19
|
+
import { openDashboard } from './cli/dashboard.js';
|
|
20
|
+
import { executeFit } from './cli/fit.js';
|
|
21
|
+
import { listChecks } from './cli/list-checks.js';
|
|
22
|
+
import { listRecipes } from './cli/list-recipes.js';
|
|
23
|
+
import {
|
|
24
|
+
saveBaseline,
|
|
25
|
+
compareToBaseline,
|
|
26
|
+
renderGateCompareOutput,
|
|
27
|
+
GateBaselineMissingError,
|
|
28
|
+
GateBaselineInvalidError,
|
|
29
|
+
DEFAULT_BASELINE_PATH,
|
|
30
|
+
} from './gate.js';
|
|
31
|
+
|
|
32
|
+
import type { CliArgs, FitOptions, ToolOptions } from '@opensip-tools/contracts';
|
|
33
|
+
import type { Tool, ToolCliContext, ToolCommandDescriptor } from '@opensip-tools/core';
|
|
34
|
+
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// COMMAND DESCRIPTORS — used by --help listings and conflict detection.
|
|
37
|
+
// =============================================================================
|
|
38
|
+
|
|
39
|
+
const FIT: ToolCommandDescriptor = {
|
|
40
|
+
name: 'fit',
|
|
41
|
+
description: 'Run fitness checks',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const DASHBOARD: ToolCommandDescriptor = {
|
|
45
|
+
name: 'dashboard',
|
|
46
|
+
description: 'Generate the HTML dashboard and open it in your browser',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const FIT_LIST: ToolCommandDescriptor = {
|
|
50
|
+
name: 'fit-list',
|
|
51
|
+
description: 'List available fitness checks',
|
|
52
|
+
aliases: ['list-checks'],
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const FIT_RECIPES: ToolCommandDescriptor = {
|
|
56
|
+
name: 'fit-recipes',
|
|
57
|
+
description: 'List available fitness recipes',
|
|
58
|
+
aliases: ['list-recipes'],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// REGISTER — wires Commander subcommands onto the CLI's program.
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
function fitOptsToCliArgs(opts: FitOptions & { quiet?: boolean; open?: boolean }): CliArgs {
|
|
66
|
+
return {
|
|
67
|
+
command: 'fit',
|
|
68
|
+
json: opts.json,
|
|
69
|
+
check: opts.check,
|
|
70
|
+
recipe: opts.recipe,
|
|
71
|
+
cwd: opts.cwd,
|
|
72
|
+
help: false,
|
|
73
|
+
list: opts.list,
|
|
74
|
+
listRecipes: opts.recipes,
|
|
75
|
+
verbose: opts.verbose,
|
|
76
|
+
reportTo: opts.reportTo,
|
|
77
|
+
apiKey: opts.apiKey,
|
|
78
|
+
exclude: opts.exclude,
|
|
79
|
+
findings: opts.findings,
|
|
80
|
+
tags: opts.tags,
|
|
81
|
+
quiet: opts.quiet === true,
|
|
82
|
+
open: opts.open === true,
|
|
83
|
+
config: opts.config,
|
|
84
|
+
gateSave: opts.gateSave === true,
|
|
85
|
+
gateCompare: opts.gateCompare === true,
|
|
86
|
+
baseline: opts.baseline,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function register(cli: ToolCliContext): void {
|
|
91
|
+
// Cast once — the contract intentionally types `program` loosely so
|
|
92
|
+
// tools aren't pinned to a specific Commander major.
|
|
93
|
+
const program = cli.program as Command;
|
|
94
|
+
|
|
95
|
+
// -- fit ------------------------------------------------------------------
|
|
96
|
+
program
|
|
97
|
+
.command(FIT.name)
|
|
98
|
+
.description(FIT.description)
|
|
99
|
+
.option('--recipe <name>', 'Use a named recipe (default, quick-smoke, backend, etc.)')
|
|
100
|
+
.option('--check <slug>', 'Run a single check by slug')
|
|
101
|
+
.option('--tags <tags>', 'Filter checks by tags (comma-separated)')
|
|
102
|
+
.option('--list', 'List available checks', false)
|
|
103
|
+
.option('--recipes', 'List available recipes', false)
|
|
104
|
+
.option('--json', 'Output structured JSON', false)
|
|
105
|
+
.option('-v, --verbose', 'Show finding details inline + findings summary', false)
|
|
106
|
+
.option('--findings', 'Show all findings grouped by check after the run', false)
|
|
107
|
+
.option('--report-to <url>', 'POST findings to a URL (OpenSIP Cloud or compatible)')
|
|
108
|
+
.option('--api-key <key>', 'API key for --report-to authentication')
|
|
109
|
+
.option('--exclude <slug>', 'Exclude check (repeatable)', (val: string, prev: string[]) => [...prev, val], [] as string[])
|
|
110
|
+
.option('--cwd <path>', 'Target directory', process.cwd())
|
|
111
|
+
.option('--config <path>', 'Path to opensip-tools.config.yml (overrides package.json pointer and default)')
|
|
112
|
+
.option('-q, --quiet', 'Suppress banner / boxes; print only the pass-fail summary', false)
|
|
113
|
+
.option('--open', 'Launch the HTML dashboard in your browser after the run completes', false)
|
|
114
|
+
.option('--debug', 'Enable debug mode for structured log output', false)
|
|
115
|
+
.option('--gate-save', 'Architecture-gate: save current findings as baseline (mutually exclusive with --gate-compare)', false)
|
|
116
|
+
.option('--gate-compare', 'Architecture-gate: compare current findings against baseline; exit 1 on regression', false)
|
|
117
|
+
.option('--baseline <path>', 'Path to baseline file for --gate-save / --gate-compare (default: opensip-tools/.runtime/baseline.sarif)')
|
|
118
|
+
.action(async (opts: FitOptions & { quiet?: boolean; open?: boolean }) => {
|
|
119
|
+
const args = fitOptsToCliArgs(opts);
|
|
120
|
+
|
|
121
|
+
// Architecture gate: --gate-save / --gate-compare. Headless,
|
|
122
|
+
// stdout-only, exit code is the gate decision.
|
|
123
|
+
if (args.gateSave === true || args.gateCompare === true) {
|
|
124
|
+
await runGateMode(args, cli);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// --list
|
|
129
|
+
if (args.list) {
|
|
130
|
+
const result = await listChecks(args.cwd);
|
|
131
|
+
if (args.json) { process.stdout.write(JSON.stringify(result, null, 2) + '\n'); return; }
|
|
132
|
+
await cli.render(result);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// --recipes
|
|
137
|
+
if (args.listRecipes) {
|
|
138
|
+
const result = await listRecipes(args.cwd);
|
|
139
|
+
if (args.json) { process.stdout.write(JSON.stringify(result, null, 2) + '\n'); return; }
|
|
140
|
+
await cli.render(result);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Main fit execution.
|
|
145
|
+
if (args.json) {
|
|
146
|
+
const fitResult = await executeFit(args);
|
|
147
|
+
if (fitResult.result.type === 'error') {
|
|
148
|
+
cli.setExitCode(fitResult.result.exitCode);
|
|
149
|
+
process.stdout.write(JSON.stringify({ error: fitResult.result.message }, null, 2) + '\n');
|
|
150
|
+
} else {
|
|
151
|
+
if (fitResult.result.type === 'fit-done' && fitResult.result.shouldFail) {
|
|
152
|
+
cli.setExitCode(EXIT_CODES.RUNTIME_ERROR);
|
|
153
|
+
}
|
|
154
|
+
process.stdout.write(JSON.stringify(fitResult.output, null, 2) + '\n');
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Visual mode — Ink-rendered live results. The CLI supplies the
|
|
160
|
+
// renderer via cli.renderLive() so this file doesn't depend on
|
|
161
|
+
// the CLI package directly.
|
|
162
|
+
await cli.renderLive('fit', args);
|
|
163
|
+
|
|
164
|
+
// --open: launch dashboard after the run when conditions allow.
|
|
165
|
+
await cli.maybeOpenDashboard({
|
|
166
|
+
openRequested: Boolean(opts.open),
|
|
167
|
+
jsonOutput: Boolean(args.json),
|
|
168
|
+
cwd: args.cwd,
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// -- dashboard ------------------------------------------------------------
|
|
173
|
+
program
|
|
174
|
+
.command(DASHBOARD.name)
|
|
175
|
+
.description(DASHBOARD.description)
|
|
176
|
+
.option('--cwd <path>', 'Target directory', process.cwd())
|
|
177
|
+
.option('--json', 'Output structured JSON', false)
|
|
178
|
+
.option('--debug', 'Enable debug mode for structured log output', false)
|
|
179
|
+
.action(async (opts: ToolOptions) => {
|
|
180
|
+
const result = await openDashboard(opts.cwd);
|
|
181
|
+
if (opts.json) {
|
|
182
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
await cli.render(result);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// -- fit-list (alias: list-checks) ----------------------------------------
|
|
189
|
+
const fitListCmd = program
|
|
190
|
+
.command(FIT_LIST.name)
|
|
191
|
+
.description(FIT_LIST.description);
|
|
192
|
+
for (const alias of FIT_LIST.aliases ?? []) fitListCmd.alias(alias);
|
|
193
|
+
fitListCmd
|
|
194
|
+
.option('--cwd <path>', 'Target directory', process.cwd())
|
|
195
|
+
.option('--json', 'Output structured JSON', false)
|
|
196
|
+
.action(async (opts: ToolOptions) => {
|
|
197
|
+
const result = await listChecks(opts.cwd);
|
|
198
|
+
if (opts.json) { process.stdout.write(JSON.stringify(result, null, 2) + '\n'); return; }
|
|
199
|
+
await cli.render(result);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// -- fit-recipes (alias: list-recipes) ------------------------------------
|
|
203
|
+
const fitRecipesCmd = program
|
|
204
|
+
.command(FIT_RECIPES.name)
|
|
205
|
+
.description(FIT_RECIPES.description);
|
|
206
|
+
for (const alias of FIT_RECIPES.aliases ?? []) fitRecipesCmd.alias(alias);
|
|
207
|
+
fitRecipesCmd
|
|
208
|
+
.option('--cwd <path>', 'Target directory', process.cwd())
|
|
209
|
+
.option('--json', 'Output structured JSON', false)
|
|
210
|
+
.action(async (opts: ToolOptions) => {
|
|
211
|
+
const result = await listRecipes(opts.cwd);
|
|
212
|
+
if (opts.json) { process.stdout.write(JSON.stringify(result, null, 2) + '\n'); return; }
|
|
213
|
+
await cli.render(result);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// =============================================================================
|
|
218
|
+
// GATE MODE — extracted helper used by `fit --gate-save` / `--gate-compare`.
|
|
219
|
+
// =============================================================================
|
|
220
|
+
|
|
221
|
+
async function runGateMode(args: CliArgs, cli: ToolCliContext): Promise<void> {
|
|
222
|
+
if (args.gateSave === true && args.gateCompare === true) {
|
|
223
|
+
cli.logger.warn({
|
|
224
|
+
evt: 'cli.gate.config_error',
|
|
225
|
+
module: 'cli:gate',
|
|
226
|
+
reason: 'mutually-exclusive flags',
|
|
227
|
+
msg: '--gate-save and --gate-compare specified together',
|
|
228
|
+
});
|
|
229
|
+
cli.setExitCode(EXIT_CODES.CONFIGURATION_ERROR);
|
|
230
|
+
process.stderr.write('Error: --gate-save and --gate-compare are mutually exclusive.\n');
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const baselinePath = args.baseline ?? DEFAULT_BASELINE_PATH;
|
|
234
|
+
const fitResult = await executeFit(args);
|
|
235
|
+
if (fitResult.result.type !== 'fit-done') {
|
|
236
|
+
cli.logger.warn({
|
|
237
|
+
evt: 'cli.gate.fit_failed',
|
|
238
|
+
module: 'cli:gate',
|
|
239
|
+
mode: args.gateSave === true ? 'save' : 'compare',
|
|
240
|
+
baselinePath,
|
|
241
|
+
reason: fitResult.result.message,
|
|
242
|
+
});
|
|
243
|
+
cli.setExitCode(fitResult.result.exitCode);
|
|
244
|
+
process.stderr.write(`Error: ${fitResult.result.message}\n`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const output = fitResult.output!;
|
|
248
|
+
try {
|
|
249
|
+
if (args.gateSave === true) {
|
|
250
|
+
saveBaseline(output, baselinePath);
|
|
251
|
+
const findingCount = output.checks.reduce((n, c) => n + c.findings.length, 0);
|
|
252
|
+
process.stdout.write(`Baseline saved to ${baselinePath}\n`);
|
|
253
|
+
process.stdout.write(` ${output.checks.length} check(s), ${findingCount} finding(s)\n`);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const result = compareToBaseline(output, baselinePath);
|
|
257
|
+
process.stdout.write(renderGateCompareOutput(result) + '\n');
|
|
258
|
+
cli.setExitCode(result.degraded ? 1 : 0);
|
|
259
|
+
return;
|
|
260
|
+
} catch (error) {
|
|
261
|
+
if (error instanceof GateBaselineMissingError || error instanceof GateBaselineInvalidError) {
|
|
262
|
+
cli.logger.warn({
|
|
263
|
+
evt: 'cli.gate.baseline_error',
|
|
264
|
+
module: 'cli:gate',
|
|
265
|
+
mode: args.gateSave === true ? 'save' : 'compare',
|
|
266
|
+
baselinePath,
|
|
267
|
+
errorType: error.name,
|
|
268
|
+
reason: error.message,
|
|
269
|
+
});
|
|
270
|
+
cli.setExitCode(EXIT_CODES.CONFIGURATION_ERROR);
|
|
271
|
+
process.stderr.write(`Error: ${error.message}\n`);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// =============================================================================
|
|
279
|
+
// EXPORT
|
|
280
|
+
// =============================================================================
|
|
281
|
+
|
|
282
|
+
export const fitnessTool: Tool = {
|
|
283
|
+
metadata: {
|
|
284
|
+
id: 'fitness',
|
|
285
|
+
version: '1.0.0',
|
|
286
|
+
description: 'Run fitness checks against a codebase',
|
|
287
|
+
},
|
|
288
|
+
commands: [FIT, DASHBOARD, FIT_LIST, FIT_RECIPES],
|
|
289
|
+
register,
|
|
290
|
+
initialize: async (): Promise<void> => {
|
|
291
|
+
// ensureChecksLoaded() is called inside the executeFit / listChecks
|
|
292
|
+
// / listRecipes paths, so a separate initialize() pass is not
|
|
293
|
+
// strictly needed today. Left as a no-op so fitness has somewhere
|
|
294
|
+
// to hang future tool-startup work (eager check-pack discovery,
|
|
295
|
+
// catalog warming, etc.) without requiring a contract change.
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// Pre-load hook setter — used by the CLI to wire project-plugin
|
|
300
|
+
// auto-sync into ensureChecksLoaded's startup path. Re-exported here
|
|
301
|
+
// so the CLI's bootstrap doesn't need to deep-import.
|
|
302
|
+
export { setPreLoadHook } from './cli/fit.js';
|