code-auditor-mcp 5.0.1 → 5.2.0
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +227 -3
- package/README.md +24 -2
- package/configs/hhra-compat.json +12 -118
- package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js +11 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +57 -52
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -1
- package/dist/analyzers/handleIdentification.d.ts.map +1 -1
- package/dist/analyzers/handleIdentification.js +4 -1
- package/dist/analyzers/handleIdentification.js.map +1 -1
- package/dist/analyzers/provenance.d.ts +9 -4
- package/dist/analyzers/provenance.d.ts.map +1 -1
- package/dist/analyzers/provenance.js +8 -25
- package/dist/analyzers/provenance.js.map +1 -1
- package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +0 -5
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/receiverRoot.d.ts +20 -0
- package/dist/analyzers/receiverRoot.d.ts.map +1 -1
- package/dist/analyzers/receiverRoot.js +42 -0
- package/dist/analyzers/receiverRoot.js.map +1 -1
- package/dist/analyzers/ruleRegistry.js +4 -4
- package/dist/analyzers/ruleRegistry.js.map +1 -1
- package/dist/analyzers/ruleTiming.d.ts +1 -1
- package/dist/analyzers/ruleTiming.js +2 -2
- package/dist/analyzers/ruleTiming.js.map +1 -1
- package/dist/analyzers/tsEcosystem.d.ts.map +1 -1
- package/dist/analyzers/tsEcosystem.js +10 -0
- package/dist/analyzers/tsEcosystem.js.map +1 -1
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +22 -26
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts +32 -15
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +189 -115
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts +0 -2
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +0 -5
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +2 -10
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js +7 -49
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
- package/dist/analyzers/universal/schema/config.js +0 -2
- package/dist/analyzers/universal/schema/config.js.map +1 -1
- package/dist/analyzers/universal/schema/types.d.ts +0 -2
- package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
- package/dist/analyzers/vendorSurfaces.d.ts +126 -0
- package/dist/analyzers/vendorSurfaces.d.ts.map +1 -0
- package/dist/analyzers/vendorSurfaces.js +580 -0
- package/dist/analyzers/vendorSurfaces.js.map +1 -0
- package/dist/auditRunner.d.ts +2 -0
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +159 -160
- package/dist/auditRunner.js.map +1 -1
- package/dist/churn/churnExtractor.d.ts +0 -1
- package/dist/churn/churnExtractor.d.ts.map +1 -1
- package/dist/churn/churnExtractor.js +2 -4
- package/dist/churn/churnExtractor.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +212 -29
- package/dist/cli.js.map +1 -1
- package/dist/codeIndex/migrations.d.ts.map +1 -1
- package/dist/codeIndex/migrations.js +4 -3
- package/dist/codeIndex/migrations.js.map +1 -1
- package/dist/codeIndexDB.d.ts +11 -2
- package/dist/codeIndexDB.d.ts.map +1 -1
- package/dist/codeIndexDB.js +27 -2
- package/dist/codeIndexDB.js.map +1 -1
- package/dist/config/configLoader.d.ts +60 -7
- package/dist/config/configLoader.d.ts.map +1 -1
- package/dist/config/configLoader.js +252 -60
- package/dist/config/configLoader.js.map +1 -1
- package/dist/config/defaults.d.ts +77 -18
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +105 -43
- package/dist/config/defaults.js.map +1 -1
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -1
- package/dist/daemon/main.d.ts +0 -1
- package/dist/daemon/main.d.ts.map +1 -1
- package/dist/daemon/main.js +31 -8
- package/dist/daemon/main.js.map +1 -1
- package/dist/dataPaths.d.ts +17 -11
- package/dist/dataPaths.d.ts.map +1 -1
- package/dist/dataPaths.js +51 -16
- package/dist/dataPaths.js.map +1 -1
- package/dist/graph/resolutionEnvironment.d.ts +61 -0
- package/dist/graph/resolutionEnvironment.d.ts.map +1 -0
- package/dist/graph/resolutionEnvironment.js +57 -0
- package/dist/graph/resolutionEnvironment.js.map +1 -0
- package/dist/hookLog.d.ts +54 -0
- package/dist/hookLog.d.ts.map +1 -0
- package/dist/hookLog.js +105 -0
- package/dist/hookLog.js.map +1 -0
- package/dist/hookLogPath.generated.d.ts +3 -0
- package/dist/hookLogPath.generated.d.ts.map +1 -0
- package/dist/hookLogPath.generated.js +8 -0
- package/dist/hookLogPath.generated.js.map +1 -0
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -7
- package/dist/index.js.map +1 -1
- package/dist/installConfig.d.ts +15 -2
- package/dist/installConfig.d.ts.map +1 -1
- package/dist/installConfig.js +17 -2
- package/dist/installConfig.js.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +18 -3
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
- package/dist/mcp-tools/workflowGuide.js +8 -8
- package/dist/mcp-tools/workflowGuide.js.map +1 -1
- package/dist/mcp-tools-shared.d.ts.map +1 -1
- package/dist/mcp-tools-shared.js +5 -2
- package/dist/mcp-tools-shared.js.map +1 -1
- package/dist/mcp-ui-simple.d.ts +5 -0
- package/dist/mcp-ui-simple.d.ts.map +1 -1
- package/dist/mcp-ui-simple.js +9 -2
- package/dist/mcp-ui-simple.js.map +1 -1
- package/dist/mcp.d.ts +0 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +36 -33
- package/dist/mcp.js.map +1 -1
- package/dist/mcpAuditJobs.d.ts +10 -0
- package/dist/mcpAuditJobs.d.ts.map +1 -1
- package/dist/mcpAuditJobs.js +10 -1
- package/dist/mcpAuditJobs.js.map +1 -1
- package/dist/mcpAutoIndex.d.ts.map +1 -1
- package/dist/mcpAutoIndex.js +2 -1
- package/dist/mcpAutoIndex.js.map +1 -1
- package/dist/phase/colorMath.d.ts +18 -5
- package/dist/phase/colorMath.d.ts.map +1 -1
- package/dist/phase/colorMath.js +88 -5
- package/dist/phase/colorMath.js.map +1 -1
- package/dist/phase/dataAccessCallsCandidates.js +1 -1
- package/dist/phase/dataAccessCallsCandidates.js.map +1 -1
- package/dist/phase/goFunctionAnalysis.d.ts +2 -2
- package/dist/phase/goFunctionAnalysis.js +2 -2
- package/dist/phase/goFunctions.d.ts +2 -2
- package/dist/phase/goFunctions.js +2 -2
- package/dist/phase/goImports.d.ts +2 -2
- package/dist/phase/goImports.js +2 -2
- package/dist/phase/goSwitches.d.ts +2 -2
- package/dist/phase/goSwitches.js +2 -2
- package/dist/phase/loopQueryCandidates.js +1 -1
- package/dist/phase/loopQueryCandidates.js.map +1 -1
- package/dist/phase/phaseModel.d.ts +37 -8
- package/dist/phase/phaseModel.d.ts.map +1 -1
- package/dist/phase/phaseModel.js +94 -46
- package/dist/phase/phaseModel.js.map +1 -1
- package/dist/phase/producers.d.ts.map +1 -1
- package/dist/phase/producers.js +27 -17
- package/dist/phase/producers.js.map +1 -1
- package/dist/phase/reachability.d.ts +44 -1
- package/dist/phase/reachability.d.ts.map +1 -1
- package/dist/phase/reachability.js +79 -0
- package/dist/phase/reachability.js.map +1 -1
- package/dist/phase/receiverConsumers.d.ts +8 -1
- package/dist/phase/receiverConsumers.d.ts.map +1 -1
- package/dist/phase/receiverConsumers.js +59 -21
- package/dist/phase/receiverConsumers.js.map +1 -1
- package/dist/phase/receiverProvenance.d.ts +23 -0
- package/dist/phase/receiverProvenance.d.ts.map +1 -1
- package/dist/phase/receiverProvenance.js +40 -0
- package/dist/phase/receiverProvenance.js.map +1 -1
- package/dist/phase/rules/crossDomain.d.ts.map +1 -1
- package/dist/phase/rules/crossDomain.js +16 -6
- package/dist/phase/rules/crossDomain.js.map +1 -1
- package/dist/phase/rules/dry.d.ts.map +1 -1
- package/dist/phase/rules/dry.js +0 -1
- package/dist/phase/rules/dry.js.map +1 -1
- package/dist/phase/rules/goRules.d.ts +2 -2
- package/dist/phase/rules/goRules.js +2 -2
- package/dist/phase/rules/secrets.d.ts +22 -8
- package/dist/phase/rules/secrets.d.ts.map +1 -1
- package/dist/phase/rules/secrets.js +48 -67
- package/dist/phase/rules/secrets.js.map +1 -1
- package/dist/phase/rules/styles.d.ts +23 -9
- package/dist/phase/rules/styles.d.ts.map +1 -1
- package/dist/phase/rules/styles.js +47 -15
- package/dist/phase/rules/styles.js.map +1 -1
- package/dist/phase/rules/unreferencedModule.d.ts.map +1 -1
- package/dist/phase/rules/unreferencedModule.js +16 -5
- package/dist/phase/rules/unreferencedModule.js.map +1 -1
- package/dist/phase/runner.d.ts +16 -7
- package/dist/phase/runner.d.ts.map +1 -1
- package/dist/phase/runner.js +32 -20
- package/dist/phase/runner.js.map +1 -1
- package/dist/phase/stylesCss.d.ts.map +1 -1
- package/dist/phase/stylesCss.js +4 -0
- package/dist/phase/stylesCss.js.map +1 -1
- package/dist/phase/stylesMarkup.d.ts.map +1 -1
- package/dist/phase/stylesMarkup.js +4 -0
- package/dist/phase/stylesMarkup.js.map +1 -1
- package/dist/phase/stylesSource.d.ts.map +1 -1
- package/dist/phase/stylesSource.js +6 -0
- package/dist/phase/stylesSource.js.map +1 -1
- package/dist/phase/testProgram.d.ts +57 -0
- package/dist/phase/testProgram.d.ts.map +1 -0
- package/dist/phase/testProgram.js +244 -0
- package/dist/phase/testProgram.js.map +1 -0
- package/dist/phase/typeDeclarations.d.ts +2 -2
- package/dist/phase/typeDeclarations.js +2 -2
- package/dist/phase/types.d.ts +54 -0
- package/dist/phase/types.d.ts.map +1 -1
- package/dist/pipelineAdapters.d.ts +1 -171
- package/dist/pipelineAdapters.d.ts.map +1 -1
- package/dist/pipelineAdapters.js +47 -1281
- package/dist/pipelineAdapters.js.map +1 -1
- package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
- package/dist/reporting/csvReportGenerator.js +0 -6
- package/dist/reporting/csvReportGenerator.js.map +1 -1
- package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
- package/dist/reporting/htmlReportGenerator.js +0 -4
- package/dist/reporting/htmlReportGenerator.js.map +1 -1
- package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
- package/dist/reporting/jsonReportGenerator.js +0 -1
- package/dist/reporting/jsonReportGenerator.js.map +1 -1
- package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
- package/dist/reporting/sarifReportGenerator.js +0 -7
- package/dist/reporting/sarifReportGenerator.js.map +1 -1
- package/dist/sqlite/driver.d.ts +17 -1
- package/dist/sqlite/driver.d.ts.map +1 -1
- package/dist/sqlite/driver.js +28 -5
- package/dist/sqlite/driver.js.map +1 -1
- package/dist/styles/cssInJsHarvest.d.ts +36 -0
- package/dist/styles/cssInJsHarvest.d.ts.map +1 -0
- package/dist/styles/cssInJsHarvest.js +78 -0
- package/dist/styles/cssInJsHarvest.js.map +1 -0
- package/dist/styles/definedClasses.d.ts +95 -0
- package/dist/styles/definedClasses.d.ts.map +1 -0
- package/dist/styles/definedClasses.js +129 -0
- package/dist/styles/definedClasses.js.map +1 -0
- package/dist/styles/markupStyleHarvest.d.ts +33 -0
- package/dist/styles/markupStyleHarvest.d.ts.map +1 -0
- package/dist/styles/markupStyleHarvest.js +73 -0
- package/dist/styles/markupStyleHarvest.js.map +1 -0
- package/dist/styles/styleExtractor.d.ts +37 -0
- package/dist/styles/styleExtractor.d.ts.map +1 -1
- package/dist/styles/styleExtractor.js +89 -33
- package/dist/styles/styleExtractor.js.map +1 -1
- package/dist/styles/styleIndexer.d.ts.map +1 -1
- package/dist/styles/styleIndexer.js +11 -10
- package/dist/styles/styleIndexer.js.map +1 -1
- package/dist/styles/tailwindExpander.d.ts.map +1 -1
- package/dist/styles/tailwindExpander.js +31 -10
- package/dist/styles/tailwindExpander.js.map +1 -1
- package/dist/telemetry.d.ts +67 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +100 -20
- package/dist/telemetry.js.map +1 -1
- package/dist/types/crossLanguage.d.ts +1 -0
- package/dist/types/crossLanguage.d.ts.map +1 -1
- package/dist/types.d.ts +36 -56
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -4
- package/dist/types.js.map +1 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/examples/.auditrc.example.json +7 -22
- package/examples/.auditrc.json +12 -155
- package/examples/.code-auditor.json +8 -51
- package/examples/nextjs.auditrc.json +7 -34
- package/examples/node-api.auditrc.json +6 -46
- package/examples/react.auditrc.json +8 -25
- package/examples/tolerant-solid.auditrc.json +12 -44
- package/package.json +13 -9
- package/plugin/.claude-plugin/manifest.json +10 -9
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/hooks/hooks.json +4 -4
- package/plugin/scripts/hook-audit.sh +14 -2
- package/plugin/scripts/hook-common.sh +41 -11
- package/plugin/scripts/hook-drift-check.sh +19 -6
- package/plugin/scripts/hook-log-path.sh +7 -0
- package/plugin/scripts/hook-self-audit.sh +14 -2
- package/plugin/scripts/hook-warm.sh +22 -17
- package/plugin/skills/code-auditor/SKILL.md +26 -3
- package/server.json +10 -4
- package/dist/__tests__/fixtures/spec-20/scripts/tool.d.ts +0 -6
- package/dist/__tests__/fixtures/spec-20/scripts/tool.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-20/scripts/tool.js +0 -12
- package/dist/__tests__/fixtures/spec-20/scripts/tool.js.map +0 -1
- package/dist/__tests__/fixtures/spec-20/src/demo-module.d.ts +0 -7
- package/dist/__tests__/fixtures/spec-20/src/demo-module.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-20/src/demo-module.js +0 -13
- package/dist/__tests__/fixtures/spec-20/src/demo-module.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-01-prepare-in-loop.d.ts +0 -14
- package/dist/__tests__/fixtures/spec-52/item-01-prepare-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-01-prepare-in-loop.js +0 -16
- package/dist/__tests__/fixtures/spec-52/item-01-prepare-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-02-prepare-bind-accumulate-batch.d.ts +0 -15
- package/dist/__tests__/fixtures/spec-52/item-02-prepare-bind-accumulate-batch.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-02-prepare-bind-accumulate-batch.js +0 -17
- package/dist/__tests__/fixtures/spec-52/item-02-prepare-bind-accumulate-batch.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts +0 -14
- package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js +0 -19
- package/dist/__tests__/fixtures/spec-52/item-03-exec-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts +0 -18
- package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js +0 -19
- package/dist/__tests__/fixtures/spec-52/item-04-storage-sql-exec-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts +0 -19
- package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.js +0 -19
- package/dist/__tests__/fixtures/spec-52/item-05-upsert-forms.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts +0 -17
- package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.js +0 -19
- package/dist/__tests__/fixtures/spec-52/item-06-chained-prepare-run-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts +0 -25
- package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.js +0 -21
- package/dist/__tests__/fixtures/spec-52/item-07-chained-prepare-bind-first-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-08-promise-all-of-statements-in-loop.d.ts +0 -15
- package/dist/__tests__/fixtures/spec-52/item-08-promise-all-of-statements-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-08-promise-all-of-statements-in-loop.js +0 -19
- package/dist/__tests__/fixtures/spec-52/item-08-promise-all-of-statements-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-09-promise-all-map-of-statements-in-loop.d.ts +0 -14
- package/dist/__tests__/fixtures/spec-52/item-09-promise-all-map-of-statements-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-09-promise-all-map-of-statements-in-loop.js +0 -14
- package/dist/__tests__/fixtures/spec-52/item-09-promise-all-map-of-statements-in-loop.js.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts +0 -15
- package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.d.ts.map +0 -1
- package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.js +0 -16
- package/dist/__tests__/fixtures/spec-52/item-10-promise-all-map-of-eager-all-in-loop.js.map +0 -1
- package/dist/languages/go/analyzer-darwin-amd64 +0 -0
- package/dist/languages/go/analyzer-darwin-arm64 +0 -0
- package/dist/languages/go/analyzer-linux-amd64 +0 -0
- package/dist/languages/go/analyzer-linux-arm64 +0 -0
- package/dist/languages/go/analyzer-src/analyzer.go +0 -643
- package/dist/languages/go/analyzer-src/dataaccess.go +0 -388
- package/dist/languages/go/analyzer-src/go.mod +0 -3
- package/dist/languages/go/analyzer-src/indexer.go +0 -268
- package/dist/languages/go/analyzer-src/parser.go +0 -461
- package/dist/languages/go/analyzer-src/solid.go +0 -311
- package/dist/languages/go/analyzer-src/testconventions.go +0 -25
- package/dist/languages/go/analyzer-src/types.go +0 -156
- package/dist/languages/go/analyzer-windows-amd64.exe +0 -0
- package/dist/languages/go/go.mod +0 -7
- package/dist/languages/go/main.go +0 -203
- package/dist/native/ast-grep-napi.darwin-arm64.node +0 -0
- package/dist/native/ast-grep-napi.darwin-x64.node +0 -0
- package/dist/native/ast-grep-napi.linux-arm64-gnu.node +0 -0
- package/dist/native/ast-grep-napi.linux-arm64-musl.node +0 -0
- package/dist/native/ast-grep-napi.linux-x64-gnu.node +0 -0
- package/dist/native/ast-grep-napi.linux-x64-musl.node +0 -0
- package/dist/native/ast-grep-napi.win32-x64-msvc.node +0 -0
- package/dist/native-bootstrap.d.ts +0 -15
- package/dist/native-bootstrap.d.ts.map +0 -1
- package/dist/native-bootstrap.js +0 -75
- package/dist/native-bootstrap.js.map +0 -1
package/dist/auditRunner.js
CHANGED
|
@@ -23,9 +23,7 @@ import { isMcpDebugEnabled, logMcpDebug, logMcpInfo } from './mcpDiagnostics.js'
|
|
|
23
23
|
import { loadBaseline, matchFindings, hashBaseline } from './baseline.js';
|
|
24
24
|
import { applyDismissals } from './dismissals.js';
|
|
25
25
|
import { computeImpact, LATENCY_BUDGET_MS } from './graph/blastRadius.js';
|
|
26
|
-
import {
|
|
27
|
-
import { normalizeDialect } from './mcp-tools/discoveryQueries.js';
|
|
28
|
-
import { detectDialect } from './languages/sql/dialectDetection.js';
|
|
26
|
+
import { buildResolutionEnvironment } from './graph/resolutionEnvironment.js';
|
|
29
27
|
// Import universal analyzers
|
|
30
28
|
import { initializeLanguages } from './languages/index.js';
|
|
31
29
|
import { initializeOrmAdapters } from './analyzers/orm/index.js';
|
|
@@ -37,12 +35,12 @@ import { writeAuditToLedger, detectRunInput } from './ledger.js';
|
|
|
37
35
|
import { runPipeline, makeVisitorStatus, getFilesProcessed, isVisitorStatus } from './pipeline.js';
|
|
38
36
|
import { getRuleTimingSortedDesc } from './analyzers/ruleTiming.js';
|
|
39
37
|
import { createFunctionIndexVisitor, createStylesCssVisitor, createStylesSourceVisitor, createStylesReducer, createInvariantsReducer, createSchemaCodeVisitor, } from './pipelineAdapters.js';
|
|
40
|
-
import { computeSizeDistributions } from './reporting/sizeDistribution.js';
|
|
41
|
-
import { splitRoutes, attributeRoutes, enabledMigratedRules } from './phase/routing.js';
|
|
42
38
|
import { runPhaseModel } from './phase/phaseModel.js';
|
|
39
|
+
import { resolveVendorSurfaces } from './analyzers/vendorSurfaces.js';
|
|
43
40
|
import { resolvePhaseThresholds } from './phase/config.js';
|
|
44
41
|
import { deriveCoverage, presentFormatsOf } from './phase/coverage.js';
|
|
45
42
|
import { MIGRATED_RULES, RULE_ANALYZER } from './phase/rules/registry.js';
|
|
43
|
+
import { computeReachabilityScores } from './phase/reachability.js';
|
|
46
44
|
import { seedDryPairs, resolveBlockConfig } from './phase/rules/dry.js';
|
|
47
45
|
import { checkUnresolvedReceiverImports, checkUnprovenQueryReceivers, checkUnresolvedQueries, checkUnparseableSql, dedupeCannotFireByReceiver } from './analyzers/universal/schema/codeAnalysis.js';
|
|
48
46
|
import { readProjectManifest, computeManifestStaleness } from './analyzers/manifestStaleness.js';
|
|
@@ -202,7 +200,7 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
202
200
|
phase: 'discovery',
|
|
203
201
|
message: `Discovering files... (scope: ${scopeResultType})`
|
|
204
202
|
});
|
|
205
|
-
const { files, skippedExtensions } = await resolveDiscoveryScope(mergedOptions, scope, fileAccounting);
|
|
203
|
+
const { files, skippedExtensions, changedScopeNoBaseline } = await resolveDiscoveryScope(mergedOptions, scope, fileAccounting);
|
|
206
204
|
throwIfAborted(mergedOptions.abortSignal);
|
|
207
205
|
// Detect changed functions for non-all scopes
|
|
208
206
|
let changedFunctions;
|
|
@@ -230,6 +228,7 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
230
228
|
scope,
|
|
231
229
|
isScoped,
|
|
232
230
|
scopeResultType,
|
|
231
|
+
changedScopeNoBaseline,
|
|
233
232
|
};
|
|
234
233
|
}
|
|
235
234
|
/**
|
|
@@ -240,6 +239,11 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
240
239
|
*/
|
|
241
240
|
async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
242
241
|
let files;
|
|
242
|
+
// True when a bare `changed` scope found no baseline in the index to diff
|
|
243
|
+
// against (an empty `functions` table). That is "the diff cannot be computed",
|
|
244
|
+
// not "nothing changed" — surfaced as a diagnostic so the run never reports a
|
|
245
|
+
// false clean. Explicit-files and all/other scopes leave this false.
|
|
246
|
+
let changedScopeNoBaseline = false;
|
|
243
247
|
// Extensions present on disk that discovery skipped (Spec 43 R5 follow-up).
|
|
244
248
|
// Populated only for the `all` scope — scoped runs are explicitly scoped by
|
|
245
249
|
// the user, so "what wasn't analyzed" there is the scope itself, not the
|
|
@@ -271,12 +275,29 @@ async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
|
271
275
|
error: err instanceof Error ? err.message : String(err)
|
|
272
276
|
});
|
|
273
277
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
278
|
+
let modifiedFiles;
|
|
279
|
+
if (mergedOptions.explicitFiles !== undefined) {
|
|
280
|
+
modifiedFiles = mergedOptions.explicitFiles;
|
|
281
|
+
}
|
|
282
|
+
else if (db) {
|
|
283
|
+
// `undefined` here means *no baseline* (an empty `functions` table) — a
|
|
284
|
+
// different answer from `[]` ("baseline present, nothing modified"). The
|
|
285
|
+
// former is reported as an uncomputable diff, never as a clean run. The
|
|
286
|
+
// `db`-unavailable case (init threw, e.g. a future schema version) keeps
|
|
287
|
+
// its existing fail-open zero-file path and the later engine-error
|
|
288
|
+
// diagnostic.
|
|
289
|
+
const detected = await db.detectModifiedFiles(path.resolve(mergedOptions.projectRoot || process.cwd()));
|
|
290
|
+
if (detected === undefined)
|
|
291
|
+
changedScopeNoBaseline = true;
|
|
292
|
+
modifiedFiles = detected ?? [];
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
modifiedFiles = [];
|
|
296
|
+
}
|
|
277
297
|
files = [...new Set(modifiedFiles.map((f) => path.resolve(f)))].sort();
|
|
278
298
|
logMcpInfo('discovery', 'changed scope resolved', {
|
|
279
|
-
fileCount: files.length
|
|
299
|
+
fileCount: files.length,
|
|
300
|
+
noBaseline: changedScopeNoBaseline
|
|
280
301
|
});
|
|
281
302
|
}
|
|
282
303
|
else if (Array.isArray(scope)) {
|
|
@@ -292,7 +313,7 @@ async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
|
292
313
|
files = discovered.files;
|
|
293
314
|
skippedExtensions = discovered.skippedExtensions;
|
|
294
315
|
}
|
|
295
|
-
return { files, skippedExtensions };
|
|
316
|
+
return { files, skippedExtensions, changedScopeNoBaseline };
|
|
296
317
|
}
|
|
297
318
|
/**
|
|
298
319
|
* Detect changed functions for a scoped run via the code index (Spec 60.1).
|
|
@@ -529,8 +550,6 @@ function buildPipelineAdapters(analyzers) {
|
|
|
529
550
|
const pipelineVisitors = [];
|
|
530
551
|
const pipelineReducers = [];
|
|
531
552
|
const pipelineDerivedReducers = [];
|
|
532
|
-
let reactBundle;
|
|
533
|
-
let solidBundle;
|
|
534
553
|
// Always-on infrastructure: function-index visitor populates the
|
|
535
554
|
// `functions` table so conventions + cross-domain reducers have data
|
|
536
555
|
// even on a cold run with no prior index sync.
|
|
@@ -569,8 +588,6 @@ function buildPipelineAdapters(analyzers) {
|
|
|
569
588
|
pipelineVisitors,
|
|
570
589
|
pipelineReducers,
|
|
571
590
|
pipelineDerivedReducers,
|
|
572
|
-
reactBundle,
|
|
573
|
-
solidBundle,
|
|
574
591
|
};
|
|
575
592
|
}
|
|
576
593
|
/**
|
|
@@ -589,16 +606,12 @@ function buildPipelineAnalyzerConfig(analyzers, mergedOptions, root, files, corp
|
|
|
589
606
|
// better-sqlite3/D1 → sqlite, mysql2 → mysql). A null dialect means the SQL
|
|
590
607
|
// facts `cannot-fire` — and `sqlDialectReason` names *why* (undetermined or
|
|
591
608
|
// ambiguous) so the abstention is visible rather than silent.
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
})()
|
|
599
|
-
: detectDialect(root);
|
|
600
|
-
const sqlDialect = detection.dialect;
|
|
601
|
-
const sqlDialectReason = detection.reason;
|
|
609
|
+
const resolution = buildResolutionEnvironment(root, {
|
|
610
|
+
databaseType: mergedOptions.databaseType,
|
|
611
|
+
importVirtualModules: mergedOptions.importVirtualModules,
|
|
612
|
+
});
|
|
613
|
+
const sqlDialect = resolution.sqlDialect;
|
|
614
|
+
const sqlDialectReason = resolution.sqlDialectReason;
|
|
602
615
|
// Spec 62 Amendment B — the missing-org-filter Stage-4 reducer reads the
|
|
603
616
|
// data-access config namespace, so it inherits the data-access analyzer's
|
|
604
617
|
// config rather than a fresh empty namespace.
|
|
@@ -662,10 +675,10 @@ function buildPipelineAnalyzerConfig(analyzers, mergedOptions, root, files, corp
|
|
|
662
675
|
_provenanceTiming: provenanceTiming,
|
|
663
676
|
files,
|
|
664
677
|
corpusFiles,
|
|
665
|
-
importVirtualModules:
|
|
666
|
-
tsconfigAliases:
|
|
667
|
-
packageEntryPoints:
|
|
668
|
-
declaredTypePackages:
|
|
678
|
+
importVirtualModules: resolution.importVirtualModules,
|
|
679
|
+
tsconfigAliases: resolution.tsconfigAliases,
|
|
680
|
+
packageEntryPoints: resolution.packageEntryPoints,
|
|
681
|
+
declaredTypePackages: resolution.declaredTypePackages,
|
|
669
682
|
// Spec 70 R1 — surfaced under `_infra` so `runPipeline` can hand the named
|
|
670
683
|
// dialect to the phase model's data-access producer without reading the
|
|
671
684
|
// data-access namespace.
|
|
@@ -713,19 +726,18 @@ function buildPipelineConfig(inputs) {
|
|
|
713
726
|
};
|
|
714
727
|
}
|
|
715
728
|
/**
|
|
716
|
-
* Run the
|
|
717
|
-
*
|
|
718
|
-
*
|
|
729
|
+
* Run the phase model — the single analysis path (Spec 68 §15) — and re-emit its
|
|
730
|
+
* findings into the correct analyzer buckets. The legacy analyzer path is
|
|
731
|
+
* deleted; there is no route split to choose between. Mutates `analyzerResults`
|
|
732
|
+
* and `pipelineAnalyzerConfig` (dry divergence).
|
|
719
733
|
*/
|
|
720
|
-
async function
|
|
734
|
+
async function runPhaseModelStage(inputs) {
|
|
721
735
|
const { mergedOptions, root, files, isScoped, pipelineAnalyzerConfig, analyzerResults, pipelineIndexHandle } = inputs;
|
|
722
736
|
let phaseFindings = [];
|
|
723
737
|
let phaseIncompleteFacts = new Map();
|
|
724
|
-
let
|
|
738
|
+
let phaseReachability;
|
|
725
739
|
let receiverDiagnostics = [];
|
|
726
|
-
|
|
727
|
-
routeAttribution = Object.fromEntries(attributeRoutes());
|
|
728
|
-
if (migrated.size > 0) {
|
|
740
|
+
if (MIGRATED_RULES.length > 0) {
|
|
729
741
|
// The `dry/diverging-clone` rule reads its knobs from `dry.divergence`.
|
|
730
742
|
const topLevelDivergence = mergedOptions.divergence;
|
|
731
743
|
if (topLevelDivergence && !pipelineAnalyzerConfig['dry']?.divergence) {
|
|
@@ -764,12 +776,17 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
764
776
|
tsconfigAliases: infraConfig.tsconfigAliases,
|
|
765
777
|
packageEntryPoints: infraConfig.packageEntryPoints,
|
|
766
778
|
indexHandle: pipelineIndexHandle,
|
|
767
|
-
enabledRules:
|
|
779
|
+
enabledRules: new Set(MIGRATED_RULES.map((r) => r.id)),
|
|
768
780
|
externalTables,
|
|
769
781
|
workerCount: resolveWorkerCount(),
|
|
770
782
|
sqlDialect: infraConfig.sqlDialect,
|
|
771
783
|
sqlDialectReason: infraConfig.sqlDialectReason,
|
|
772
784
|
declaredTypePackages: infraConfig.declaredTypePackages,
|
|
785
|
+
// Item B (reissued) — resolve each vendor's declaration from the tree under
|
|
786
|
+
// analysis (its own node_modules / workspace path) once per run. The
|
|
787
|
+
// loop-query / data-access producers read these resolved surfaces; nothing
|
|
788
|
+
// about a vendor's API is committed and nothing is fetched at analysis time.
|
|
789
|
+
vendorSurfaces: resolveVendorSurfaces(root),
|
|
773
790
|
// Spec 70 2b — the diverging-clone write: seed `dry_pair_history` from the
|
|
774
791
|
// phase `code-block` fact (replacing `createDryVisitor`/`persistDryPairs`).
|
|
775
792
|
persistDryPairHistory: (facts) => {
|
|
@@ -780,6 +797,11 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
780
797
|
});
|
|
781
798
|
phaseFindings = phaseResult.findings;
|
|
782
799
|
phaseIncompleteFacts = phaseResult.incompleteFacts;
|
|
800
|
+
const reachabilityFact = phaseResult.facts.get('reachability');
|
|
801
|
+
const fileImports = phaseResult.facts.get('file-imports');
|
|
802
|
+
phaseReachability = reachabilityFact && fileImports
|
|
803
|
+
? computeReachabilityScores(fileImports, reachabilityFact)
|
|
804
|
+
: undefined;
|
|
783
805
|
// Spec 69 §10 + Part 2b — re-home the pre-pass's diagnostics (deleted from
|
|
784
806
|
// `pipeline.ts`) on the phase result. Cannot-fire: re-derive per file from
|
|
785
807
|
// `phaseResult.unprovenQueryReceivers` + `phaseResult.unresolvedImports`, keyed
|
|
@@ -787,12 +809,34 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
787
809
|
// receivers/imports never reached it). Manifest-stale: the ecosystem-list
|
|
788
810
|
// self-check, unchanged from the deleted `buildPipelineResult` loop.
|
|
789
811
|
receiverDiagnostics = await buildReceiverDiagnostics(phaseResult.unprovenQueryReceivers, phaseResult.unresolvedImports, phaseResult.unresolvedQuerySites, phaseResult.unparseableSql, root);
|
|
790
|
-
//
|
|
791
|
-
|
|
812
|
+
// Spec 68 §8 — `unreferenced-module`'s unproven modules: a module with no
|
|
813
|
+
// resolved importer while the graph carries a computed-specifier dynamic
|
|
814
|
+
// import. The rule withholds the dead-code finding for these; this surfaces
|
|
815
|
+
// the disposition (with its reason) as a coverage diagnostic instead.
|
|
816
|
+
for (const m of phaseResult.unprovenModules) {
|
|
817
|
+
receiverDiagnostics.push({
|
|
818
|
+
analyzerName: 'dependency-graph',
|
|
819
|
+
kind: 'unresolved-dynamic-import',
|
|
820
|
+
message: m.reason,
|
|
821
|
+
file: m.file,
|
|
822
|
+
line: m.line,
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
// §15 — a rule that could not run (fail-open, missing dependency) reported
|
|
826
|
+
// itself on the phase result's diagnostic channel. Merge those alongside the
|
|
827
|
+
// receiver-diagnostics the pre-pass re-derived, so the styles
|
|
828
|
+
// `undefined-class-disabled` diagnostic (re-homed from the deleted
|
|
829
|
+
// `initTailwindProbe`) reaches the same off-ladder surface.
|
|
830
|
+
receiverDiagnostics.push(...phaseResult.diagnostics);
|
|
831
|
+
// Strip the migrated rules' legacy emission from every analyzer result —
|
|
832
|
+
// the phase model is their single source of truth now (§15), and the legacy
|
|
833
|
+
// factories that keep running for their infra side-effect (styles reducer,
|
|
834
|
+
// schema-code visitor) still emit their migrated findings alongside. This is
|
|
835
|
+
// a direct projection of MIGRATED_RULES, not a route split: there is no
|
|
836
|
+
// "phase vs legacy" choice anymore, only discarding a stale duplicate.
|
|
837
|
+
const migratedRules = new Set(MIGRATED_RULES.map((r) => r.id));
|
|
792
838
|
for (const result of Object.values(analyzerResults)) {
|
|
793
|
-
|
|
794
|
-
result.violations = result.violations.filter((v) => !migrated.has(v.rule));
|
|
795
|
-
strippedCount += before - result.violations.length;
|
|
839
|
+
result.violations = result.violations.filter((v) => !migratedRules.has(v.rule));
|
|
796
840
|
}
|
|
797
841
|
// Re-emit phase findings as violations, bucketed by the rule's analyzer.
|
|
798
842
|
const byAnalyzer = new Map();
|
|
@@ -842,13 +886,8 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
842
886
|
analyzerResults[analyzer] = makeEmptyAnalyzerResult(analyzer, phaseFiles.length);
|
|
843
887
|
}
|
|
844
888
|
}
|
|
845
|
-
logMcpInfo('analysis', 'phase model (both paths)', {
|
|
846
|
-
migrated: migrated.size,
|
|
847
|
-
stripped: strippedCount,
|
|
848
|
-
reemitted: phaseFindings.length,
|
|
849
|
-
});
|
|
850
889
|
}
|
|
851
|
-
return { phaseFindings, phaseIncompleteFacts,
|
|
890
|
+
return { phaseFindings, phaseIncompleteFacts, phaseReachability, receiverDiagnostics };
|
|
852
891
|
}
|
|
853
892
|
/**
|
|
854
893
|
* Spec 69 §10 + Part 2b — re-derive the pre-pass's coverage diagnostics from the
|
|
@@ -968,29 +1007,6 @@ export async function persistDryPairs(dryPairs, root) {
|
|
|
968
1007
|
// dry_pair_history persistence is advisory — non-fatal
|
|
969
1008
|
}
|
|
970
1009
|
}
|
|
971
|
-
/**
|
|
972
|
-
* Run the React analyzer's cross-component finalization (require-error-boundary
|
|
973
|
-
* / raw-element checks), appending extra violations into the `react` result.
|
|
974
|
-
*/
|
|
975
|
-
async function finalizeReact(reactBundle, analyzerResults, pipelineAnalyzerConfig) {
|
|
976
|
-
if (reactBundle) {
|
|
977
|
-
try {
|
|
978
|
-
const reactResult = analyzerResults['react'];
|
|
979
|
-
if (reactResult) {
|
|
980
|
-
// Pass the react namespace (not the whole namespaced config) so
|
|
981
|
-
// finalize reads `requireErrorBoundaries`/`rawElementCheck` at the
|
|
982
|
-
// same level the visitor's `context.config` does.
|
|
983
|
-
const extraViolations = await reactBundle.finalizeCrossComponent(pipelineAnalyzerConfig['react'] ?? {});
|
|
984
|
-
reactResult.violations.push(...extraViolations);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
catch (err) {
|
|
988
|
-
logMcpInfo('analysis', 'react finalization failed (non-fatal)', {
|
|
989
|
-
error: err instanceof Error ? err.message : String(err)
|
|
990
|
-
});
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
1010
|
/**
|
|
995
1011
|
* Build the pipeline, run it, and fold its outputs — plus the both-paths phase
|
|
996
1012
|
* split and derived coverage — into a single result bundle for `run`.
|
|
@@ -1001,7 +1017,7 @@ async function runPipelineStage(inputs) {
|
|
|
1001
1017
|
let indexFactsWritten = 0;
|
|
1002
1018
|
let writeIndexFactsMs = 0;
|
|
1003
1019
|
const { auditIndex, pipelineIndexHandle, indexSkipDiagnostic } = await initializeAuditIndex(root);
|
|
1004
|
-
const { pipelineVisitors, pipelineReducers, pipelineDerivedReducers,
|
|
1020
|
+
const { pipelineVisitors, pipelineReducers, pipelineDerivedReducers, } = buildPipelineAdapters(analyzers);
|
|
1005
1021
|
// ── Safeguard warnings ────────────────────────────────────────────────
|
|
1006
1022
|
if (auditIndex && analyzers.includes('cross-domain')) {
|
|
1007
1023
|
const suCount = auditIndex.rawSql.count('schema_usage');
|
|
@@ -1017,6 +1033,7 @@ async function runPipelineStage(inputs) {
|
|
|
1017
1033
|
// Outputs hoisted so derived coverage (after the split) can read them.
|
|
1018
1034
|
let phaseFindings = [];
|
|
1019
1035
|
let phaseIncompleteFacts = new Map();
|
|
1036
|
+
let phaseReachability;
|
|
1020
1037
|
let pipelineCoverage;
|
|
1021
1038
|
let pipelineTableCatalog;
|
|
1022
1039
|
let pipelineStageTiming;
|
|
@@ -1029,7 +1046,6 @@ async function runPipelineStage(inputs) {
|
|
|
1029
1046
|
let pipelineTestCoverage;
|
|
1030
1047
|
let pipelineDeadClusters;
|
|
1031
1048
|
let pipelineSizeDistributions;
|
|
1032
|
-
let routeAttribution;
|
|
1033
1049
|
let receiverDiagnostics = [];
|
|
1034
1050
|
if (hasPipelineAnalyzers) {
|
|
1035
1051
|
const pipelineAnalyzerConfig = buildPipelineAnalyzerConfig(analyzers, mergedOptions, root, files, corpusFiles, provenanceTiming);
|
|
@@ -1058,13 +1074,12 @@ async function runPipelineStage(inputs) {
|
|
|
1058
1074
|
status: ar.status?.status,
|
|
1059
1075
|
});
|
|
1060
1076
|
}
|
|
1061
|
-
await
|
|
1062
|
-
const split = await applyPhaseModelSplit({
|
|
1077
|
+
const split = await runPhaseModelStage({
|
|
1063
1078
|
mergedOptions, root, files, isScoped, pipelineAnalyzerConfig, analyzerResults, pipelineIndexHandle,
|
|
1064
1079
|
});
|
|
1065
1080
|
phaseFindings = split.phaseFindings;
|
|
1066
1081
|
phaseIncompleteFacts = split.phaseIncompleteFacts;
|
|
1067
|
-
|
|
1082
|
+
phaseReachability = split.phaseReachability;
|
|
1068
1083
|
receiverDiagnostics = split.receiverDiagnostics;
|
|
1069
1084
|
// Spec 68 §8 — derived coverage, computed AFTER the split so phaseFindings
|
|
1070
1085
|
// holds the migrated rules' re-emitted findings.
|
|
@@ -1072,7 +1087,7 @@ async function runPipelineStage(inputs) {
|
|
|
1072
1087
|
rules: MIGRATED_RULES,
|
|
1073
1088
|
findings: phaseFindings,
|
|
1074
1089
|
presentFormats: presentFormatsOf(files),
|
|
1075
|
-
enabledRules:
|
|
1090
|
+
enabledRules: new Set(MIGRATED_RULES.map((r) => r.id)),
|
|
1076
1091
|
incompleteFacts: phaseIncompleteFacts,
|
|
1077
1092
|
groupOf: (ruleId) => RULE_ANALYZER.get(ruleId) ?? ruleId,
|
|
1078
1093
|
});
|
|
@@ -1094,11 +1109,6 @@ async function runPipelineStage(inputs) {
|
|
|
1094
1109
|
];
|
|
1095
1110
|
pipelineTestCoverage = pipelineResult.metadata?.testCoverage;
|
|
1096
1111
|
pipelineDeadClusters = pipelineResult.metadata?.deadClusters;
|
|
1097
|
-
// Spec 60 R2 — aggregate the SOLID analyzer's raw size readings.
|
|
1098
|
-
if (solidBundle) {
|
|
1099
|
-
const samples = await solidBundle.getSizeSamples();
|
|
1100
|
-
pipelineSizeDistributions = computeSizeDistributions(samples);
|
|
1101
|
-
}
|
|
1102
1112
|
}
|
|
1103
1113
|
catch (error) {
|
|
1104
1114
|
if (error instanceof AuditAbortedError) {
|
|
@@ -1144,6 +1154,7 @@ async function runPipelineStage(inputs) {
|
|
|
1144
1154
|
analyzerResults,
|
|
1145
1155
|
phaseFindings,
|
|
1146
1156
|
phaseIncompleteFacts,
|
|
1157
|
+
phaseReachability,
|
|
1147
1158
|
pipelineCoverage,
|
|
1148
1159
|
pipelineTableCatalog,
|
|
1149
1160
|
pipelineStageTiming,
|
|
@@ -1156,7 +1167,6 @@ async function runPipelineStage(inputs) {
|
|
|
1156
1167
|
pipelineTestCoverage,
|
|
1157
1168
|
pipelineDeadClusters,
|
|
1158
1169
|
pipelineSizeDistributions,
|
|
1159
|
-
routeAttribution,
|
|
1160
1170
|
indexFactsWritten,
|
|
1161
1171
|
writeIndexFactsMs,
|
|
1162
1172
|
};
|
|
@@ -1260,75 +1270,40 @@ function stampAnalyzerFields(ordered) {
|
|
|
1260
1270
|
}
|
|
1261
1271
|
}
|
|
1262
1272
|
/**
|
|
1263
|
-
* Spec 13 R2 — attach
|
|
1264
|
-
*
|
|
1265
|
-
* order as tiebreaker
|
|
1266
|
-
*
|
|
1273
|
+
* Spec 13 R2 — attach a reachability score to every violation and reorder within
|
|
1274
|
+
* severity tiers (live code first: entry point → imported → dead), original
|
|
1275
|
+
* order as tiebreaker. Derived from the phase `reachability` fact (reverse
|
|
1276
|
+
* import adjacency + package entry points); no DB read. Advisory — a missing
|
|
1277
|
+
* fact (a run where the phase model produced no reachability) leaves every
|
|
1278
|
+
* finding at the neutral 0.5 and preserves original order.
|
|
1267
1279
|
*/
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
const
|
|
1277
|
-
for (const
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
const reachabilityByFile = new Map();
|
|
1284
|
-
const reachRows = indexDb.rawDb
|
|
1285
|
-
.prepare("SELECT node_key, weight FROM graph_cache WHERE graph_type = 'reachability'")
|
|
1286
|
-
.all();
|
|
1287
|
-
for (const row of reachRows) {
|
|
1288
|
-
reachabilityByFile.set(row.node_key, row.weight);
|
|
1289
|
-
}
|
|
1290
|
-
for (const analyzerName of Object.keys(ordered)) {
|
|
1291
|
-
const result = ordered[analyzerName];
|
|
1292
|
-
const violations = result.violations;
|
|
1293
|
-
for (const v of violations) {
|
|
1294
|
-
const funcName = v.symbol;
|
|
1295
|
-
const file = v.file;
|
|
1296
|
-
// Try function-level hotspot first: "filePath::symbol"
|
|
1297
|
-
const funcTarget = funcName ? `${file}::${funcName}` : undefined;
|
|
1298
|
-
v.hotspot = (funcTarget ? hotspotByTarget.get(funcTarget) : undefined)
|
|
1299
|
-
?? hotspotByFile.get(file)
|
|
1300
|
-
?? 0;
|
|
1301
|
-
// Files with no cross-language entities (no reachability data) get a
|
|
1302
|
-
// neutral 0.5 so we never demote a finding we know nothing about.
|
|
1303
|
-
v.reachability = reachabilityByFile.get(file) ?? 0.5;
|
|
1304
|
-
}
|
|
1305
|
-
const severityOrder = {
|
|
1306
|
-
critical: 0,
|
|
1307
|
-
severe: 1,
|
|
1308
|
-
high: 2,
|
|
1309
|
-
info: 3,
|
|
1310
|
-
};
|
|
1311
|
-
const indexed = violations.map((v, i) => ({ v, i }));
|
|
1312
|
-
indexed.sort((a, b) => {
|
|
1313
|
-
const sevA = severityOrder[a.v.severity] ?? 99;
|
|
1314
|
-
const sevB = severityOrder[b.v.severity] ?? 99;
|
|
1315
|
-
if (sevA !== sevB)
|
|
1316
|
-
return sevA - sevB;
|
|
1317
|
-
const reachA = a.v.reachability ?? 0.5;
|
|
1318
|
-
const reachB = b.v.reachability ?? 0.5;
|
|
1319
|
-
if (reachA !== reachB)
|
|
1320
|
-
return reachB - reachA;
|
|
1321
|
-
const hsA = a.v.hotspot ?? 0;
|
|
1322
|
-
const hsB = b.v.hotspot ?? 0;
|
|
1323
|
-
if (hsA !== hsB)
|
|
1324
|
-
return hsB - hsA;
|
|
1325
|
-
return a.i - b.i;
|
|
1326
|
-
});
|
|
1327
|
-
result.violations = indexed.map((x) => x.v);
|
|
1280
|
+
function applyReachabilityRanking(ordered, reachabilityByFile) {
|
|
1281
|
+
const severityOrder = {
|
|
1282
|
+
critical: 0,
|
|
1283
|
+
severe: 1,
|
|
1284
|
+
high: 2,
|
|
1285
|
+
info: 3,
|
|
1286
|
+
};
|
|
1287
|
+
for (const result of Object.values(ordered)) {
|
|
1288
|
+
const violations = result.violations;
|
|
1289
|
+
for (const v of violations) {
|
|
1290
|
+
// A file absent from the corpus graph gets a neutral 0.5 so we never
|
|
1291
|
+
// demote a finding we know nothing about.
|
|
1292
|
+
v.reachability = reachabilityByFile?.get(v.file) ?? 0.5;
|
|
1328
1293
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1294
|
+
const indexed = violations.map((v, i) => ({ v, i }));
|
|
1295
|
+
indexed.sort((a, b) => {
|
|
1296
|
+
const sevA = severityOrder[a.v.severity] ?? 99;
|
|
1297
|
+
const sevB = severityOrder[b.v.severity] ?? 99;
|
|
1298
|
+
if (sevA !== sevB)
|
|
1299
|
+
return sevA - sevB;
|
|
1300
|
+
const reachA = a.v.reachability ?? 0.5;
|
|
1301
|
+
const reachB = b.v.reachability ?? 0.5;
|
|
1302
|
+
if (reachA !== reachB)
|
|
1303
|
+
return reachB - reachA;
|
|
1304
|
+
return a.i - b.i;
|
|
1305
|
+
});
|
|
1306
|
+
result.violations = indexed.map((x) => x.v);
|
|
1332
1307
|
}
|
|
1333
1308
|
}
|
|
1334
1309
|
/**
|
|
@@ -1375,7 +1350,7 @@ function classifyBaselineFindings(ordered, mergedOptions, files, isScoped) {
|
|
|
1375
1350
|
* Spec 60 size/test/distribution reports), and hook-contract-clean violations.
|
|
1376
1351
|
*/
|
|
1377
1352
|
function buildAuditResult(inputs) {
|
|
1378
|
-
const { ordered, files, analyzers, mergedOptions, isScoped, scopeResultType, indexFactsWritten, writeIndexFactsMs, startTime, startCpu, provenanceTiming, blastRadius, zeroFilesDiagnostics, pipelineDiagnostics, rejected, lintConfigDiagnostics, configPath, baselineMetadata, pipelineCoverage,
|
|
1353
|
+
const { ordered, files, analyzers, mergedOptions, isScoped, scopeResultType, indexFactsWritten, writeIndexFactsMs, startTime, startCpu, provenanceTiming, blastRadius, changedScopeNoBaseline, zeroFilesDiagnostics, pipelineDiagnostics, rejected, lintConfigDiagnostics, configPath, baselineMetadata, pipelineCoverage, pipelineTableCatalog, pipelineStageTiming, thresholdChanges, thresholdSources, pipelineSkippedFiles, pipelineUnparsedFiles, skippedExtensions, pipelineInputPresence, pipelineRuleTiming, pipelineFileAccounting, pipelineTestCoverage, pipelineDeadClusters, pipelineSizeDistributions, collectedFunctions, fileToFunctionsMap, } = inputs;
|
|
1379
1354
|
// Spec 69 §10 R4 — count query-shaped call sites whose DB receiver is
|
|
1380
1355
|
// unproven, keyed by the analyzer that owns the receiver-resolution
|
|
1381
1356
|
// instrument (`schema`). This is the site-level `cannot-fire` surface that
|
|
@@ -1386,6 +1361,19 @@ function buildAuditResult(inputs) {
|
|
|
1386
1361
|
continue;
|
|
1387
1362
|
unprovenSitesByAnalyzer.set(d.analyzerName, (unprovenSitesByAnalyzer.get(d.analyzerName) ?? 0) + 1);
|
|
1388
1363
|
}
|
|
1364
|
+
// A bare `changed` scope that found no baseline to diff against (an empty
|
|
1365
|
+
// `functions` table) is reported as an uncomputable diff, never as a clean
|
|
1366
|
+
// run. The diagnostic names both possible causes: the index was never
|
|
1367
|
+
// populated, or it was discarded (e.g. after corruption).
|
|
1368
|
+
const noBaselineDiagnostics = changedScopeNoBaseline
|
|
1369
|
+
? [{
|
|
1370
|
+
analyzerName: 'code-index',
|
|
1371
|
+
kind: 'no-baseline',
|
|
1372
|
+
message: 'Cannot determine what changed: the code index holds no baseline to diff against ' +
|
|
1373
|
+
'(no previously indexed files). No index has been built yet, or a prior index was ' +
|
|
1374
|
+
'discarded. Run a full audit to build the baseline, then re-run `changed`.',
|
|
1375
|
+
}]
|
|
1376
|
+
: [];
|
|
1389
1377
|
const summary = generateSummary(ordered, files.length, unprovenSitesByAnalyzer);
|
|
1390
1378
|
return {
|
|
1391
1379
|
timestamp: new Date(),
|
|
@@ -1403,8 +1391,9 @@ function buildAuditResult(inputs) {
|
|
|
1403
1391
|
scope: scopeResultType,
|
|
1404
1392
|
provenanceResolutionMs: provenanceTiming.totalMs,
|
|
1405
1393
|
...(blastRadius && { blastRadius }),
|
|
1406
|
-
...((zeroFilesDiagnostics.length > 0 || (pipelineDiagnostics?.length ?? 0) > 0 || rejected.length > 0 || lintConfigDiagnostics.length > 0) && {
|
|
1394
|
+
...((noBaselineDiagnostics.length > 0 || zeroFilesDiagnostics.length > 0 || (pipelineDiagnostics?.length ?? 0) > 0 || rejected.length > 0 || lintConfigDiagnostics.length > 0) && {
|
|
1407
1395
|
diagnostics: [
|
|
1396
|
+
...noBaselineDiagnostics,
|
|
1408
1397
|
...zeroFilesDiagnostics,
|
|
1409
1398
|
...(pipelineDiagnostics ?? []),
|
|
1410
1399
|
...lintConfigDiagnostics,
|
|
@@ -1419,7 +1408,6 @@ function buildAuditResult(inputs) {
|
|
|
1419
1408
|
}),
|
|
1420
1409
|
...(baselineMetadata && { baseline: baselineMetadata }),
|
|
1421
1410
|
...(pipelineCoverage && { coverage: pipelineCoverage }),
|
|
1422
|
-
...(routeAttribution && { routeAttribution }),
|
|
1423
1411
|
...(pipelineTableCatalog && { tableCatalog: pipelineTableCatalog }),
|
|
1424
1412
|
...(pipelineStageTiming && { stageTiming: pipelineStageTiming }),
|
|
1425
1413
|
...(thresholdChanges.length > 0 && { thresholdChanges }),
|
|
@@ -1498,7 +1486,7 @@ export function createAuditRunner(options = {}) {
|
|
|
1498
1486
|
// discovery (full `all` scope) and the pipeline (stage 1/2) so every touched
|
|
1499
1487
|
// file lands in exactly one terminal state and the balance can be asserted.
|
|
1500
1488
|
const fileAccounting = new FileAccounting();
|
|
1501
|
-
const { files, changedFunctions, skippedExtensions, blastRadius, corpusFiles, scope, isScoped, scopeResultType, } = await discoverAuditFiles(mergedOptions, root, fileAccounting);
|
|
1489
|
+
const { files, changedFunctions, skippedExtensions, blastRadius, corpusFiles, scope, isScoped, scopeResultType, changedScopeNoBaseline, } = await discoverAuditFiles(mergedOptions, root, fileAccounting);
|
|
1502
1490
|
const { collectedFunctions, fileToFunctionsMap } = await collectIndexedFunctions(mergedOptions, files);
|
|
1503
1491
|
// Run analyzers
|
|
1504
1492
|
// Spec 68 §15 — no selection model: the full pipeline always runs. `indexOnly`
|
|
@@ -1516,7 +1504,7 @@ export function createAuditRunner(options = {}) {
|
|
|
1516
1504
|
mergedOptions, root, files, corpusFiles, isScoped, fileAccounting,
|
|
1517
1505
|
styleConsumedFiles, styleContributingFiles, analyzers, provenanceTiming,
|
|
1518
1506
|
});
|
|
1519
|
-
const { analyzerResults, phaseFindings, phaseIncompleteFacts, pipelineCoverage, pipelineTableCatalog, pipelineStageTiming, pipelineSkippedFiles, pipelineUnparsedFiles, pipelineInputPresence, pipelineRuleTiming, pipelineFileAccounting, pipelineDiagnostics, pipelineTestCoverage, pipelineDeadClusters, pipelineSizeDistributions,
|
|
1507
|
+
const { analyzerResults, phaseFindings, phaseIncompleteFacts, phaseReachability, pipelineCoverage, pipelineTableCatalog, pipelineStageTiming, pipelineSkippedFiles, pipelineUnparsedFiles, pipelineInputPresence, pipelineRuleTiming, pipelineFileAccounting, pipelineDiagnostics, pipelineTestCoverage, pipelineDeadClusters, pipelineSizeDistributions, indexFactsWritten, writeIndexFactsMs, } = pipeline;
|
|
1520
1508
|
// ── Zero-files diagnostic ─────────────────────────────────────────────
|
|
1521
1509
|
// Extracted to runZeroFilesDiagnostics() for testability. Runs against the
|
|
1522
1510
|
// raw analyzerResults before truthiness filtering so the "no result" pass
|
|
@@ -1532,8 +1520,8 @@ export function createAuditRunner(options = {}) {
|
|
|
1532
1520
|
// Normalize the analyzer field on every violation to its result key (the
|
|
1533
1521
|
// single source of truth — see stampAnalyzerFields).
|
|
1534
1522
|
stampAnalyzerFields(orderedAnalyzerResults);
|
|
1535
|
-
// Spec 13 R2 —
|
|
1536
|
-
|
|
1523
|
+
// Spec 13 R2 — reachability scoring & finding reordering (advisory).
|
|
1524
|
+
applyReachabilityRanking(orderedAnalyzerResults, phaseReachability);
|
|
1537
1525
|
// Hook-contract guard: no violation may carry an empty file path, line 0, or
|
|
1538
1526
|
// missing line. A sentinel violation with file:'' broke the Claude Code hook's
|
|
1539
1527
|
// JSON consumer (Spec 15 regression); line:0 from CrossDomainAnalyzer broke it
|
|
@@ -1558,6 +1546,7 @@ export function createAuditRunner(options = {}) {
|
|
|
1558
1546
|
startCpu,
|
|
1559
1547
|
provenanceTiming,
|
|
1560
1548
|
blastRadius,
|
|
1549
|
+
changedScopeNoBaseline,
|
|
1561
1550
|
zeroFilesDiagnostics,
|
|
1562
1551
|
pipelineDiagnostics,
|
|
1563
1552
|
rejected,
|
|
@@ -1565,7 +1554,6 @@ export function createAuditRunner(options = {}) {
|
|
|
1565
1554
|
configPath,
|
|
1566
1555
|
baselineMetadata,
|
|
1567
1556
|
pipelineCoverage,
|
|
1568
|
-
routeAttribution,
|
|
1569
1557
|
pipelineTableCatalog,
|
|
1570
1558
|
pipelineStageTiming,
|
|
1571
1559
|
thresholdChanges,
|
|
@@ -1765,6 +1753,7 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1765
1753
|
let criticalIssues = 0;
|
|
1766
1754
|
let severe = 0;
|
|
1767
1755
|
let high = 0;
|
|
1756
|
+
let heldOut = 0;
|
|
1768
1757
|
const violationsByCategory = {};
|
|
1769
1758
|
const byAnalyzer = {};
|
|
1770
1759
|
for (const [analyzer, result] of Object.entries(analyzerResults)) {
|
|
@@ -1772,6 +1761,8 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1772
1761
|
for (const violation of result.violations) {
|
|
1773
1762
|
totalViolations++;
|
|
1774
1763
|
analyzerViolations++;
|
|
1764
|
+
if (violation.gateExcluded)
|
|
1765
|
+
heldOut++;
|
|
1775
1766
|
switch (violation.severity) {
|
|
1776
1767
|
case 'critical':
|
|
1777
1768
|
criticalIssues++;
|
|
@@ -1798,6 +1789,12 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1798
1789
|
.sort(([, a], [, b]) => b - a)
|
|
1799
1790
|
.slice(0, 5)
|
|
1800
1791
|
.map(([type, count]) => ({ type, count }));
|
|
1792
|
+
// Spec 69 §10 R4 follow-up — the site-level cannot-fire total, summed across
|
|
1793
|
+
// analyzers, so the headline can state findings + unproven sites + held-out
|
|
1794
|
+
// readings together without re-deriving from per-analyzer buckets.
|
|
1795
|
+
let unprovenSites = 0;
|
|
1796
|
+
for (const n of unprovenSitesByAnalyzer.values())
|
|
1797
|
+
unprovenSites += n;
|
|
1801
1798
|
return {
|
|
1802
1799
|
totalFiles: filesAnalyzed,
|
|
1803
1800
|
totalViolations,
|
|
@@ -1806,7 +1803,9 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1806
1803
|
high,
|
|
1807
1804
|
violationsByCategory,
|
|
1808
1805
|
byAnalyzer,
|
|
1809
|
-
topIssues
|
|
1806
|
+
topIssues,
|
|
1807
|
+
unprovenSites,
|
|
1808
|
+
heldOut
|
|
1810
1809
|
};
|
|
1811
1810
|
}
|
|
1812
1811
|
/**
|