code-auditor-mcp 5.0.2 → 5.3.3
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 +326 -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/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 +35 -14
- package/dist/analyzers/reactAnalyzer.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/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/UniversalDRYAnalyzer.d.ts +0 -2
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js +4 -5
- package/dist/analyzers/universal/UniversalDRYAnalyzer.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/codeAnalysis.d.ts.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.js +51 -3
- package/dist/analyzers/universal/schema/codeAnalysis.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 +9 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +198 -146
- package/dist/auditRunner.js.map +1 -1
- package/dist/cacheGc.d.ts +88 -0
- package/dist/cacheGc.d.ts.map +1 -0
- package/dist/cacheGc.js +196 -0
- package/dist/cacheGc.js.map +1 -0
- 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 +260 -47
- 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 +137 -43
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +174 -101
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/effectiveConfig.d.ts +1 -1
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +4 -6
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/config/pathProfiles.d.ts +4 -3
- package/dist/config/pathProfiles.d.ts.map +1 -1
- package/dist/config/pathProfiles.js +3 -2
- package/dist/config/pathProfiles.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 +11 -4
- package/dist/daemon/main.js.map +1 -1
- package/dist/dataPaths.d.ts +32 -9
- package/dist/dataPaths.d.ts.map +1 -1
- package/dist/dataPaths.js +69 -16
- package/dist/dataPaths.js.map +1 -1
- 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/installer.d.ts.map +1 -1
- package/dist/installer.js +2 -1
- package/dist/installer.js.map +1 -1
- package/dist/languages/adapterBridge.d.ts +11 -0
- package/dist/languages/adapterBridge.d.ts.map +1 -1
- package/dist/languages/adapterBridge.js +11 -0
- package/dist/languages/adapterBridge.js.map +1 -1
- package/dist/languages/types.d.ts +8 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts +13 -0
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +135 -18
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
- package/dist/ledger.d.ts +7 -0
- package/dist/ledger.d.ts.map +1 -1
- package/dist/ledger.js +7 -0
- package/dist/ledger.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/mcpDiagnostics.d.ts +2 -0
- package/dist/mcpDiagnostics.d.ts.map +1 -1
- package/dist/mcpDiagnostics.js +2 -0
- package/dist/mcpDiagnostics.js.map +1 -1
- package/dist/phase/candidates.d.ts +53 -0
- package/dist/phase/candidates.d.ts.map +1 -0
- package/dist/phase/candidates.js +67 -0
- package/dist/phase/candidates.js.map +1 -0
- 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/imports.d.ts.map +1 -1
- package/dist/phase/imports.js +1 -0
- package/dist/phase/imports.js.map +1 -1
- package/dist/phase/loopQueryCandidates.js +1 -1
- package/dist/phase/loopQueryCandidates.js.map +1 -1
- package/dist/phase/oracles.d.ts +28 -0
- package/dist/phase/oracles.d.ts.map +1 -1
- package/dist/phase/oracles.js +28 -0
- package/dist/phase/oracles.js.map +1 -1
- package/dist/phase/phaseModel.d.ts +47 -8
- package/dist/phase/phaseModel.d.ts.map +1 -1
- package/dist/phase/phaseModel.js +44 -8
- package/dist/phase/phaseModel.js.map +1 -1
- package/dist/phase/producers.d.ts.map +1 -1
- package/dist/phase/producers.js +24 -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/rules/conventions.d.ts.map +1 -1
- package/dist/phase/rules/conventions.js +6 -2
- package/dist/phase/rules/conventions.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/dataAccess.d.ts.map +1 -1
- package/dist/phase/rules/dataAccess.js +13 -0
- package/dist/phase/rules/dataAccess.js.map +1 -1
- package/dist/phase/rules/documentation.d.ts.map +1 -1
- package/dist/phase/rules/documentation.js +11 -1
- package/dist/phase/rules/documentation.js.map +1 -1
- package/dist/phase/rules/dry.d.ts +16 -7
- package/dist/phase/rules/dry.d.ts.map +1 -1
- package/dist/phase/rules/dry.js +51 -32
- 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 +75 -69
- 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 +61 -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 +32 -10
- 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/stringLiterals.d.ts.map +1 -1
- package/dist/phase/stringLiterals.js +16 -7
- package/dist/phase/stringLiterals.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 +104 -0
- package/dist/phase/types.d.ts.map +1 -1
- package/dist/pipeline.d.ts +4 -0
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +4 -0
- package/dist/pipeline.js.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/services/auditJobService.d.ts +15 -0
- package/dist/services/auditJobService.d.ts.map +1 -1
- package/dist/services/auditJobService.js +15 -0
- package/dist/services/auditJobService.js.map +1 -1
- package/dist/services/projectTaskHelpers.d.ts +7 -0
- package/dist/services/projectTaskHelpers.d.ts.map +1 -1
- package/dist/services/projectTaskHelpers.js +7 -0
- package/dist/services/projectTaskHelpers.js.map +1 -1
- package/dist/services/whitelistService.d.ts +28 -0
- package/dist/services/whitelistService.d.ts.map +1 -1
- package/dist/services/whitelistService.js +28 -0
- package/dist/services/whitelistService.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/styles/tailwindUtilityExpander.d.ts +4 -0
- package/dist/styles/tailwindUtilityExpander.d.ts.map +1 -1
- package/dist/styles/tailwindUtilityExpander.js +4 -0
- package/dist/styles/tailwindUtilityExpander.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 +73 -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 +8 -5
- 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 +25 -10
- package/plugin/scripts/hook-common.sh +12 -7
- package/plugin/scripts/hook-drift-check.sh +10 -1
- package/plugin/scripts/hook-log-path.sh +7 -0
- package/plugin/scripts/hook-self-audit.sh +21 -6
- package/plugin/scripts/hook-warm.sh +17 -11
- package/plugin/skills/code-auditor/SKILL.md +26 -3
- package/server.json +2 -2
- 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
|
@@ -30,17 +30,18 @@ import { initializeOrmAdapters } from './analyzers/orm/index.js';
|
|
|
30
30
|
import { syncStyleIndex } from './styles/styleIndexer.js';
|
|
31
31
|
import { CodeIndexDB } from './codeIndexDB.js';
|
|
32
32
|
import { notifyLegacyIndexLocation } from './legacyIndexNotice.js';
|
|
33
|
+
import { gcStaleCacheDirsOnce } from './cacheGc.js';
|
|
33
34
|
import { writeAuditToLedger, detectRunInput } from './ledger.js';
|
|
34
35
|
// Pipeline imports (Spec 25 — pipeline replaces hand-rolled analyzer loop)
|
|
35
36
|
import { runPipeline, makeVisitorStatus, getFilesProcessed, isVisitorStatus } from './pipeline.js';
|
|
36
37
|
import { getRuleTimingSortedDesc } from './analyzers/ruleTiming.js';
|
|
37
38
|
import { createFunctionIndexVisitor, createStylesCssVisitor, createStylesSourceVisitor, createStylesReducer, createInvariantsReducer, createSchemaCodeVisitor, } from './pipelineAdapters.js';
|
|
38
|
-
import { computeSizeDistributions } from './reporting/sizeDistribution.js';
|
|
39
|
-
import { splitRoutes, attributeRoutes, enabledMigratedRules } from './phase/routing.js';
|
|
40
39
|
import { runPhaseModel } from './phase/phaseModel.js';
|
|
40
|
+
import { resolveVendorSurfaces } from './analyzers/vendorSurfaces.js';
|
|
41
41
|
import { resolvePhaseThresholds } from './phase/config.js';
|
|
42
42
|
import { deriveCoverage, presentFormatsOf } from './phase/coverage.js';
|
|
43
43
|
import { MIGRATED_RULES, RULE_ANALYZER } from './phase/rules/registry.js';
|
|
44
|
+
import { computeReachabilityScores } from './phase/reachability.js';
|
|
44
45
|
import { seedDryPairs, resolveBlockConfig } from './phase/rules/dry.js';
|
|
45
46
|
import { checkUnresolvedReceiverImports, checkUnprovenQueryReceivers, checkUnresolvedQueries, checkUnparseableSql, dedupeCannotFireByReceiver } from './analyzers/universal/schema/codeAnalysis.js';
|
|
46
47
|
import { readProjectManifest, computeManifestStaleness } from './analyzers/manifestStaleness.js';
|
|
@@ -171,8 +172,10 @@ async function resolveRunConfig(baseOptions, runOptions) {
|
|
|
171
172
|
lintThresholds,
|
|
172
173
|
presets: resolvedPresets,
|
|
173
174
|
});
|
|
174
|
-
// Always merge built-in path profiles
|
|
175
|
-
// .
|
|
175
|
+
// Always merge built-in path profiles (none ship today — the compiled-in
|
|
176
|
+
// "scripts-and-tests" gate exemption was removed). This stays as the seam
|
|
177
|
+
// that would apply any future built-in profile to corpus audits and to
|
|
178
|
+
// projects without a .codeauditor.json.
|
|
176
179
|
mergedOptions.pathProfiles = mergePathProfiles(mergedOptions.pathProfiles, mergedOptions.builtin);
|
|
177
180
|
return {
|
|
178
181
|
mergedOptions,
|
|
@@ -200,7 +203,7 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
200
203
|
phase: 'discovery',
|
|
201
204
|
message: `Discovering files... (scope: ${scopeResultType})`
|
|
202
205
|
});
|
|
203
|
-
const { files, skippedExtensions } = await resolveDiscoveryScope(mergedOptions, scope, fileAccounting);
|
|
206
|
+
const { files, skippedExtensions, changedScopeNoBaseline } = await resolveDiscoveryScope(mergedOptions, scope, fileAccounting);
|
|
204
207
|
throwIfAborted(mergedOptions.abortSignal);
|
|
205
208
|
// Detect changed functions for non-all scopes
|
|
206
209
|
let changedFunctions;
|
|
@@ -228,6 +231,7 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
228
231
|
scope,
|
|
229
232
|
isScoped,
|
|
230
233
|
scopeResultType,
|
|
234
|
+
changedScopeNoBaseline,
|
|
231
235
|
};
|
|
232
236
|
}
|
|
233
237
|
/**
|
|
@@ -238,6 +242,11 @@ async function discoverAuditFiles(mergedOptions, root, fileAccounting) {
|
|
|
238
242
|
*/
|
|
239
243
|
async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
240
244
|
let files;
|
|
245
|
+
// True when a bare `changed` scope found no baseline in the index to diff
|
|
246
|
+
// against (an empty `functions` table). That is "the diff cannot be computed",
|
|
247
|
+
// not "nothing changed" — surfaced as a diagnostic so the run never reports a
|
|
248
|
+
// false clean. Explicit-files and all/other scopes leave this false.
|
|
249
|
+
let changedScopeNoBaseline = false;
|
|
241
250
|
// Extensions present on disk that discovery skipped (Spec 43 R5 follow-up).
|
|
242
251
|
// Populated only for the `all` scope — scoped runs are explicitly scoped by
|
|
243
252
|
// the user, so "what wasn't analyzed" there is the scope itself, not the
|
|
@@ -269,12 +278,29 @@ async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
|
269
278
|
error: err instanceof Error ? err.message : String(err)
|
|
270
279
|
});
|
|
271
280
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
let modifiedFiles;
|
|
282
|
+
if (mergedOptions.explicitFiles !== undefined) {
|
|
283
|
+
modifiedFiles = mergedOptions.explicitFiles;
|
|
284
|
+
}
|
|
285
|
+
else if (db) {
|
|
286
|
+
// `undefined` here means *no baseline* (an empty `functions` table) — a
|
|
287
|
+
// different answer from `[]` ("baseline present, nothing modified"). The
|
|
288
|
+
// former is reported as an uncomputable diff, never as a clean run. The
|
|
289
|
+
// `db`-unavailable case (init threw, e.g. a future schema version) keeps
|
|
290
|
+
// its existing fail-open zero-file path and the later engine-error
|
|
291
|
+
// diagnostic.
|
|
292
|
+
const detected = await db.detectModifiedFiles(path.resolve(mergedOptions.projectRoot || process.cwd()));
|
|
293
|
+
if (detected === undefined)
|
|
294
|
+
changedScopeNoBaseline = true;
|
|
295
|
+
modifiedFiles = detected ?? [];
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
modifiedFiles = [];
|
|
299
|
+
}
|
|
275
300
|
files = [...new Set(modifiedFiles.map((f) => path.resolve(f)))].sort();
|
|
276
301
|
logMcpInfo('discovery', 'changed scope resolved', {
|
|
277
|
-
fileCount: files.length
|
|
302
|
+
fileCount: files.length,
|
|
303
|
+
noBaseline: changedScopeNoBaseline
|
|
278
304
|
});
|
|
279
305
|
}
|
|
280
306
|
else if (Array.isArray(scope)) {
|
|
@@ -290,7 +316,7 @@ async function resolveDiscoveryScope(mergedOptions, scope, fileAccounting) {
|
|
|
290
316
|
files = discovered.files;
|
|
291
317
|
skippedExtensions = discovered.skippedExtensions;
|
|
292
318
|
}
|
|
293
|
-
return { files, skippedExtensions };
|
|
319
|
+
return { files, skippedExtensions, changedScopeNoBaseline };
|
|
294
320
|
}
|
|
295
321
|
/**
|
|
296
322
|
* Detect changed functions for a scoped run via the code index (Spec 60.1).
|
|
@@ -527,8 +553,6 @@ function buildPipelineAdapters(analyzers) {
|
|
|
527
553
|
const pipelineVisitors = [];
|
|
528
554
|
const pipelineReducers = [];
|
|
529
555
|
const pipelineDerivedReducers = [];
|
|
530
|
-
let reactBundle;
|
|
531
|
-
let solidBundle;
|
|
532
556
|
// Always-on infrastructure: function-index visitor populates the
|
|
533
557
|
// `functions` table so conventions + cross-domain reducers have data
|
|
534
558
|
// even on a cold run with no prior index sync.
|
|
@@ -567,8 +591,6 @@ function buildPipelineAdapters(analyzers) {
|
|
|
567
591
|
pipelineVisitors,
|
|
568
592
|
pipelineReducers,
|
|
569
593
|
pipelineDerivedReducers,
|
|
570
|
-
reactBundle,
|
|
571
|
-
solidBundle,
|
|
572
594
|
};
|
|
573
595
|
}
|
|
574
596
|
/**
|
|
@@ -707,19 +729,20 @@ function buildPipelineConfig(inputs) {
|
|
|
707
729
|
};
|
|
708
730
|
}
|
|
709
731
|
/**
|
|
710
|
-
* Run the
|
|
711
|
-
*
|
|
712
|
-
*
|
|
732
|
+
* Run the phase model — the single analysis path (Spec 68 §15) — and re-emit its
|
|
733
|
+
* findings into the correct analyzer buckets. The legacy analyzer path is
|
|
734
|
+
* deleted; there is no route split to choose between. Mutates `analyzerResults`
|
|
735
|
+
* and `pipelineAnalyzerConfig` (dry divergence).
|
|
713
736
|
*/
|
|
714
|
-
async function
|
|
737
|
+
async function runPhaseModelStage(inputs) {
|
|
715
738
|
const { mergedOptions, root, files, isScoped, pipelineAnalyzerConfig, analyzerResults, pipelineIndexHandle } = inputs;
|
|
716
739
|
let phaseFindings = [];
|
|
717
740
|
let phaseIncompleteFacts = new Map();
|
|
718
|
-
let
|
|
741
|
+
let phaseReachability;
|
|
719
742
|
let receiverDiagnostics = [];
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (
|
|
743
|
+
let phaseCandidates = [];
|
|
744
|
+
let receiverResolutions = 0;
|
|
745
|
+
if (MIGRATED_RULES.length > 0) {
|
|
723
746
|
// The `dry/diverging-clone` rule reads its knobs from `dry.divergence`.
|
|
724
747
|
const topLevelDivergence = mergedOptions.divergence;
|
|
725
748
|
if (topLevelDivergence && !pipelineAnalyzerConfig['dry']?.divergence) {
|
|
@@ -758,12 +781,17 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
758
781
|
tsconfigAliases: infraConfig.tsconfigAliases,
|
|
759
782
|
packageEntryPoints: infraConfig.packageEntryPoints,
|
|
760
783
|
indexHandle: pipelineIndexHandle,
|
|
761
|
-
enabledRules:
|
|
784
|
+
enabledRules: new Set(MIGRATED_RULES.map((r) => r.id)),
|
|
762
785
|
externalTables,
|
|
763
786
|
workerCount: resolveWorkerCount(),
|
|
764
787
|
sqlDialect: infraConfig.sqlDialect,
|
|
765
788
|
sqlDialectReason: infraConfig.sqlDialectReason,
|
|
766
789
|
declaredTypePackages: infraConfig.declaredTypePackages,
|
|
790
|
+
// Item B (reissued) — resolve each vendor's declaration from the tree under
|
|
791
|
+
// analysis (its own node_modules / workspace path) once per run. The
|
|
792
|
+
// loop-query / data-access producers read these resolved surfaces; nothing
|
|
793
|
+
// about a vendor's API is committed and nothing is fetched at analysis time.
|
|
794
|
+
vendorSurfaces: resolveVendorSurfaces(root),
|
|
767
795
|
// Spec 70 2b — the diverging-clone write: seed `dry_pair_history` from the
|
|
768
796
|
// phase `code-block` fact (replacing `createDryVisitor`/`persistDryPairs`).
|
|
769
797
|
persistDryPairHistory: (facts) => {
|
|
@@ -774,6 +802,13 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
774
802
|
});
|
|
775
803
|
phaseFindings = phaseResult.findings;
|
|
776
804
|
phaseIncompleteFacts = phaseResult.incompleteFacts;
|
|
805
|
+
phaseCandidates = [...phaseResult.candidates];
|
|
806
|
+
receiverResolutions = phaseResult.receiverResolutions;
|
|
807
|
+
const reachabilityFact = phaseResult.facts.get('reachability');
|
|
808
|
+
const fileImports = phaseResult.facts.get('file-imports');
|
|
809
|
+
phaseReachability = reachabilityFact && fileImports
|
|
810
|
+
? computeReachabilityScores(fileImports, reachabilityFact)
|
|
811
|
+
: undefined;
|
|
777
812
|
// Spec 69 §10 + Part 2b — re-home the pre-pass's diagnostics (deleted from
|
|
778
813
|
// `pipeline.ts`) on the phase result. Cannot-fire: re-derive per file from
|
|
779
814
|
// `phaseResult.unprovenQueryReceivers` + `phaseResult.unresolvedImports`, keyed
|
|
@@ -781,12 +816,34 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
781
816
|
// receivers/imports never reached it). Manifest-stale: the ecosystem-list
|
|
782
817
|
// self-check, unchanged from the deleted `buildPipelineResult` loop.
|
|
783
818
|
receiverDiagnostics = await buildReceiverDiagnostics(phaseResult.unprovenQueryReceivers, phaseResult.unresolvedImports, phaseResult.unresolvedQuerySites, phaseResult.unparseableSql, root);
|
|
784
|
-
//
|
|
785
|
-
|
|
819
|
+
// Spec 68 §8 — `unreferenced-module`'s unproven modules: a module with no
|
|
820
|
+
// resolved importer while the graph carries a computed-specifier dynamic
|
|
821
|
+
// import. The rule withholds the dead-code finding for these; this surfaces
|
|
822
|
+
// the disposition (with its reason) as a coverage diagnostic instead.
|
|
823
|
+
for (const m of phaseResult.unprovenModules) {
|
|
824
|
+
receiverDiagnostics.push({
|
|
825
|
+
analyzerName: 'dependency-graph',
|
|
826
|
+
kind: 'unresolved-dynamic-import',
|
|
827
|
+
message: m.reason,
|
|
828
|
+
file: m.file,
|
|
829
|
+
line: m.line,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
// §15 — a rule that could not run (fail-open, missing dependency) reported
|
|
833
|
+
// itself on the phase result's diagnostic channel. Merge those alongside the
|
|
834
|
+
// receiver-diagnostics the pre-pass re-derived, so the styles
|
|
835
|
+
// `undefined-class-disabled` diagnostic (re-homed from the deleted
|
|
836
|
+
// `initTailwindProbe`) reaches the same off-ladder surface.
|
|
837
|
+
receiverDiagnostics.push(...phaseResult.diagnostics);
|
|
838
|
+
// Strip the migrated rules' legacy emission from every analyzer result —
|
|
839
|
+
// the phase model is their single source of truth now (§15), and the legacy
|
|
840
|
+
// factories that keep running for their infra side-effect (styles reducer,
|
|
841
|
+
// schema-code visitor) still emit their migrated findings alongside. This is
|
|
842
|
+
// a direct projection of MIGRATED_RULES, not a route split: there is no
|
|
843
|
+
// "phase vs legacy" choice anymore, only discarding a stale duplicate.
|
|
844
|
+
const migratedRules = new Set(MIGRATED_RULES.map((r) => r.id));
|
|
786
845
|
for (const result of Object.values(analyzerResults)) {
|
|
787
|
-
|
|
788
|
-
result.violations = result.violations.filter((v) => !migrated.has(v.rule));
|
|
789
|
-
strippedCount += before - result.violations.length;
|
|
846
|
+
result.violations = result.violations.filter((v) => !migratedRules.has(v.rule));
|
|
790
847
|
}
|
|
791
848
|
// Re-emit phase findings as violations, bucketed by the rule's analyzer.
|
|
792
849
|
const byAnalyzer = new Map();
|
|
@@ -836,13 +893,8 @@ async function applyPhaseModelSplit(inputs) {
|
|
|
836
893
|
analyzerResults[analyzer] = makeEmptyAnalyzerResult(analyzer, phaseFiles.length);
|
|
837
894
|
}
|
|
838
895
|
}
|
|
839
|
-
logMcpInfo('analysis', 'phase model (both paths)', {
|
|
840
|
-
migrated: migrated.size,
|
|
841
|
-
stripped: strippedCount,
|
|
842
|
-
reemitted: phaseFindings.length,
|
|
843
|
-
});
|
|
844
896
|
}
|
|
845
|
-
return { phaseFindings, phaseIncompleteFacts,
|
|
897
|
+
return { phaseFindings, phaseIncompleteFacts, phaseReachability, receiverDiagnostics, phaseCandidates, receiverResolutions };
|
|
846
898
|
}
|
|
847
899
|
/**
|
|
848
900
|
* Spec 69 §10 + Part 2b — re-derive the pre-pass's coverage diagnostics from the
|
|
@@ -962,29 +1014,6 @@ export async function persistDryPairs(dryPairs, root) {
|
|
|
962
1014
|
// dry_pair_history persistence is advisory — non-fatal
|
|
963
1015
|
}
|
|
964
1016
|
}
|
|
965
|
-
/**
|
|
966
|
-
* Run the React analyzer's cross-component finalization (require-error-boundary
|
|
967
|
-
* / raw-element checks), appending extra violations into the `react` result.
|
|
968
|
-
*/
|
|
969
|
-
async function finalizeReact(reactBundle, analyzerResults, pipelineAnalyzerConfig) {
|
|
970
|
-
if (reactBundle) {
|
|
971
|
-
try {
|
|
972
|
-
const reactResult = analyzerResults['react'];
|
|
973
|
-
if (reactResult) {
|
|
974
|
-
// Pass the react namespace (not the whole namespaced config) so
|
|
975
|
-
// finalize reads `requireErrorBoundaries`/`rawElementCheck` at the
|
|
976
|
-
// same level the visitor's `context.config` does.
|
|
977
|
-
const extraViolations = await reactBundle.finalizeCrossComponent(pipelineAnalyzerConfig['react'] ?? {});
|
|
978
|
-
reactResult.violations.push(...extraViolations);
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
catch (err) {
|
|
982
|
-
logMcpInfo('analysis', 'react finalization failed (non-fatal)', {
|
|
983
|
-
error: err instanceof Error ? err.message : String(err)
|
|
984
|
-
});
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
1017
|
/**
|
|
989
1018
|
* Build the pipeline, run it, and fold its outputs — plus the both-paths phase
|
|
990
1019
|
* split and derived coverage — into a single result bundle for `run`.
|
|
@@ -995,7 +1024,7 @@ async function runPipelineStage(inputs) {
|
|
|
995
1024
|
let indexFactsWritten = 0;
|
|
996
1025
|
let writeIndexFactsMs = 0;
|
|
997
1026
|
const { auditIndex, pipelineIndexHandle, indexSkipDiagnostic } = await initializeAuditIndex(root);
|
|
998
|
-
const { pipelineVisitors, pipelineReducers, pipelineDerivedReducers,
|
|
1027
|
+
const { pipelineVisitors, pipelineReducers, pipelineDerivedReducers, } = buildPipelineAdapters(analyzers);
|
|
999
1028
|
// ── Safeguard warnings ────────────────────────────────────────────────
|
|
1000
1029
|
if (auditIndex && analyzers.includes('cross-domain')) {
|
|
1001
1030
|
const suCount = auditIndex.rawSql.count('schema_usage');
|
|
@@ -1011,6 +1040,9 @@ async function runPipelineStage(inputs) {
|
|
|
1011
1040
|
// Outputs hoisted so derived coverage (after the split) can read them.
|
|
1012
1041
|
let phaseFindings = [];
|
|
1013
1042
|
let phaseIncompleteFacts = new Map();
|
|
1043
|
+
let phaseReachability;
|
|
1044
|
+
let phaseCandidates = [];
|
|
1045
|
+
let receiverResolutions = 0;
|
|
1014
1046
|
let pipelineCoverage;
|
|
1015
1047
|
let pipelineTableCatalog;
|
|
1016
1048
|
let pipelineStageTiming;
|
|
@@ -1023,7 +1055,6 @@ async function runPipelineStage(inputs) {
|
|
|
1023
1055
|
let pipelineTestCoverage;
|
|
1024
1056
|
let pipelineDeadClusters;
|
|
1025
1057
|
let pipelineSizeDistributions;
|
|
1026
|
-
let routeAttribution;
|
|
1027
1058
|
let receiverDiagnostics = [];
|
|
1028
1059
|
if (hasPipelineAnalyzers) {
|
|
1029
1060
|
const pipelineAnalyzerConfig = buildPipelineAnalyzerConfig(analyzers, mergedOptions, root, files, corpusFiles, provenanceTiming);
|
|
@@ -1052,21 +1083,22 @@ async function runPipelineStage(inputs) {
|
|
|
1052
1083
|
status: ar.status?.status,
|
|
1053
1084
|
});
|
|
1054
1085
|
}
|
|
1055
|
-
await
|
|
1056
|
-
const split = await applyPhaseModelSplit({
|
|
1086
|
+
const split = await runPhaseModelStage({
|
|
1057
1087
|
mergedOptions, root, files, isScoped, pipelineAnalyzerConfig, analyzerResults, pipelineIndexHandle,
|
|
1058
1088
|
});
|
|
1059
1089
|
phaseFindings = split.phaseFindings;
|
|
1060
1090
|
phaseIncompleteFacts = split.phaseIncompleteFacts;
|
|
1061
|
-
|
|
1091
|
+
phaseReachability = split.phaseReachability;
|
|
1062
1092
|
receiverDiagnostics = split.receiverDiagnostics;
|
|
1093
|
+
phaseCandidates = split.phaseCandidates;
|
|
1094
|
+
receiverResolutions = split.receiverResolutions;
|
|
1063
1095
|
// Spec 68 §8 — derived coverage, computed AFTER the split so phaseFindings
|
|
1064
1096
|
// holds the migrated rules' re-emitted findings.
|
|
1065
1097
|
pipelineCoverage = deriveCoverage({
|
|
1066
1098
|
rules: MIGRATED_RULES,
|
|
1067
1099
|
findings: phaseFindings,
|
|
1068
1100
|
presentFormats: presentFormatsOf(files),
|
|
1069
|
-
enabledRules:
|
|
1101
|
+
enabledRules: new Set(MIGRATED_RULES.map((r) => r.id)),
|
|
1070
1102
|
incompleteFacts: phaseIncompleteFacts,
|
|
1071
1103
|
groupOf: (ruleId) => RULE_ANALYZER.get(ruleId) ?? ruleId,
|
|
1072
1104
|
});
|
|
@@ -1088,11 +1120,6 @@ async function runPipelineStage(inputs) {
|
|
|
1088
1120
|
];
|
|
1089
1121
|
pipelineTestCoverage = pipelineResult.metadata?.testCoverage;
|
|
1090
1122
|
pipelineDeadClusters = pipelineResult.metadata?.deadClusters;
|
|
1091
|
-
// Spec 60 R2 — aggregate the SOLID analyzer's raw size readings.
|
|
1092
|
-
if (solidBundle) {
|
|
1093
|
-
const samples = await solidBundle.getSizeSamples();
|
|
1094
|
-
pipelineSizeDistributions = computeSizeDistributions(samples);
|
|
1095
|
-
}
|
|
1096
1123
|
}
|
|
1097
1124
|
catch (error) {
|
|
1098
1125
|
if (error instanceof AuditAbortedError) {
|
|
@@ -1138,6 +1165,9 @@ async function runPipelineStage(inputs) {
|
|
|
1138
1165
|
analyzerResults,
|
|
1139
1166
|
phaseFindings,
|
|
1140
1167
|
phaseIncompleteFacts,
|
|
1168
|
+
phaseReachability,
|
|
1169
|
+
phaseCandidates,
|
|
1170
|
+
receiverResolutions,
|
|
1141
1171
|
pipelineCoverage,
|
|
1142
1172
|
pipelineTableCatalog,
|
|
1143
1173
|
pipelineStageTiming,
|
|
@@ -1150,7 +1180,6 @@ async function runPipelineStage(inputs) {
|
|
|
1150
1180
|
pipelineTestCoverage,
|
|
1151
1181
|
pipelineDeadClusters,
|
|
1152
1182
|
pipelineSizeDistributions,
|
|
1153
|
-
routeAttribution,
|
|
1154
1183
|
indexFactsWritten,
|
|
1155
1184
|
writeIndexFactsMs,
|
|
1156
1185
|
};
|
|
@@ -1254,75 +1283,40 @@ function stampAnalyzerFields(ordered) {
|
|
|
1254
1283
|
}
|
|
1255
1284
|
}
|
|
1256
1285
|
/**
|
|
1257
|
-
* Spec 13 R2 — attach
|
|
1258
|
-
*
|
|
1259
|
-
* order as tiebreaker
|
|
1260
|
-
*
|
|
1286
|
+
* Spec 13 R2 — attach a reachability score to every violation and reorder within
|
|
1287
|
+
* severity tiers (live code first: entry point → imported → dead), original
|
|
1288
|
+
* order as tiebreaker. Derived from the phase `reachability` fact (reverse
|
|
1289
|
+
* import adjacency + package entry points); no DB read. Advisory — a missing
|
|
1290
|
+
* fact (a run where the phase model produced no reachability) leaves every
|
|
1291
|
+
* finding at the neutral 0.5 and preserves original order.
|
|
1261
1292
|
*/
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
const
|
|
1271
|
-
for (const
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
const reachabilityByFile = new Map();
|
|
1278
|
-
const reachRows = indexDb.rawDb
|
|
1279
|
-
.prepare("SELECT node_key, weight FROM graph_cache WHERE graph_type = 'reachability'")
|
|
1280
|
-
.all();
|
|
1281
|
-
for (const row of reachRows) {
|
|
1282
|
-
reachabilityByFile.set(row.node_key, row.weight);
|
|
1283
|
-
}
|
|
1284
|
-
for (const analyzerName of Object.keys(ordered)) {
|
|
1285
|
-
const result = ordered[analyzerName];
|
|
1286
|
-
const violations = result.violations;
|
|
1287
|
-
for (const v of violations) {
|
|
1288
|
-
const funcName = v.symbol;
|
|
1289
|
-
const file = v.file;
|
|
1290
|
-
// Try function-level hotspot first: "filePath::symbol"
|
|
1291
|
-
const funcTarget = funcName ? `${file}::${funcName}` : undefined;
|
|
1292
|
-
v.hotspot = (funcTarget ? hotspotByTarget.get(funcTarget) : undefined)
|
|
1293
|
-
?? hotspotByFile.get(file)
|
|
1294
|
-
?? 0;
|
|
1295
|
-
// Files with no cross-language entities (no reachability data) get a
|
|
1296
|
-
// neutral 0.5 so we never demote a finding we know nothing about.
|
|
1297
|
-
v.reachability = reachabilityByFile.get(file) ?? 0.5;
|
|
1298
|
-
}
|
|
1299
|
-
const severityOrder = {
|
|
1300
|
-
critical: 0,
|
|
1301
|
-
severe: 1,
|
|
1302
|
-
high: 2,
|
|
1303
|
-
info: 3,
|
|
1304
|
-
};
|
|
1305
|
-
const indexed = violations.map((v, i) => ({ v, i }));
|
|
1306
|
-
indexed.sort((a, b) => {
|
|
1307
|
-
const sevA = severityOrder[a.v.severity] ?? 99;
|
|
1308
|
-
const sevB = severityOrder[b.v.severity] ?? 99;
|
|
1309
|
-
if (sevA !== sevB)
|
|
1310
|
-
return sevA - sevB;
|
|
1311
|
-
const reachA = a.v.reachability ?? 0.5;
|
|
1312
|
-
const reachB = b.v.reachability ?? 0.5;
|
|
1313
|
-
if (reachA !== reachB)
|
|
1314
|
-
return reachB - reachA;
|
|
1315
|
-
const hsA = a.v.hotspot ?? 0;
|
|
1316
|
-
const hsB = b.v.hotspot ?? 0;
|
|
1317
|
-
if (hsA !== hsB)
|
|
1318
|
-
return hsB - hsA;
|
|
1319
|
-
return a.i - b.i;
|
|
1320
|
-
});
|
|
1321
|
-
result.violations = indexed.map((x) => x.v);
|
|
1293
|
+
function applyReachabilityRanking(ordered, reachabilityByFile) {
|
|
1294
|
+
const severityOrder = {
|
|
1295
|
+
critical: 0,
|
|
1296
|
+
severe: 1,
|
|
1297
|
+
high: 2,
|
|
1298
|
+
info: 3,
|
|
1299
|
+
};
|
|
1300
|
+
for (const result of Object.values(ordered)) {
|
|
1301
|
+
const violations = result.violations;
|
|
1302
|
+
for (const v of violations) {
|
|
1303
|
+
// A file absent from the corpus graph gets a neutral 0.5 so we never
|
|
1304
|
+
// demote a finding we know nothing about.
|
|
1305
|
+
v.reachability = reachabilityByFile?.get(v.file) ?? 0.5;
|
|
1322
1306
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1307
|
+
const indexed = violations.map((v, i) => ({ v, i }));
|
|
1308
|
+
indexed.sort((a, b) => {
|
|
1309
|
+
const sevA = severityOrder[a.v.severity] ?? 99;
|
|
1310
|
+
const sevB = severityOrder[b.v.severity] ?? 99;
|
|
1311
|
+
if (sevA !== sevB)
|
|
1312
|
+
return sevA - sevB;
|
|
1313
|
+
const reachA = a.v.reachability ?? 0.5;
|
|
1314
|
+
const reachB = b.v.reachability ?? 0.5;
|
|
1315
|
+
if (reachA !== reachB)
|
|
1316
|
+
return reachB - reachA;
|
|
1317
|
+
return a.i - b.i;
|
|
1318
|
+
});
|
|
1319
|
+
result.violations = indexed.map((x) => x.v);
|
|
1326
1320
|
}
|
|
1327
1321
|
}
|
|
1328
1322
|
/**
|
|
@@ -1369,18 +1363,54 @@ function classifyBaselineFindings(ordered, mergedOptions, files, isScoped) {
|
|
|
1369
1363
|
* Spec 60 size/test/distribution reports), and hook-contract-clean violations.
|
|
1370
1364
|
*/
|
|
1371
1365
|
function buildAuditResult(inputs) {
|
|
1372
|
-
const { ordered, files, analyzers, mergedOptions, isScoped, scopeResultType, indexFactsWritten, writeIndexFactsMs, startTime, startCpu, provenanceTiming, blastRadius, zeroFilesDiagnostics, pipelineDiagnostics, rejected, lintConfigDiagnostics, configPath, baselineMetadata, pipelineCoverage,
|
|
1366
|
+
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, phaseCandidates, receiverResolutions, cacheGc, } = inputs;
|
|
1373
1367
|
// Spec 69 §10 R4 — count query-shaped call sites whose DB receiver is
|
|
1374
1368
|
// unproven, keyed by the analyzer that owns the receiver-resolution
|
|
1375
1369
|
// instrument (`schema`). This is the site-level `cannot-fire` surface that
|
|
1376
1370
|
// `summary.byAnalyzer[].unprovenSites` carries per analyzer.
|
|
1377
1371
|
const unprovenSitesByAnalyzer = new Map();
|
|
1372
|
+
// K9 — the same site-level `cannot-fire` surface, keyed by the *rule* each
|
|
1373
|
+
// unproven site renders unreadable (from `details.affectedRules`) and the
|
|
1374
|
+
// *cause* that produced it (`details.cause`). `byAnalyzer[].unprovenSites`
|
|
1375
|
+
// answers "which analyzer produced these?"; this answers "which rule may have
|
|
1376
|
+
// under-reported?" — the discriminant the raw 465-site total hid. One site
|
|
1377
|
+
// affects every rule in its `affectedRules` list, so the per-rule `count` is
|
|
1378
|
+
// the number of unproven sites that could have produced a finding under it.
|
|
1379
|
+
const unprovenSitesByRule = new Map();
|
|
1378
1380
|
for (const d of pipelineDiagnostics ?? []) {
|
|
1379
1381
|
if (d.kind !== 'cannot-fire' || d.analyzerName !== 'schema')
|
|
1380
1382
|
continue;
|
|
1381
1383
|
unprovenSitesByAnalyzer.set(d.analyzerName, (unprovenSitesByAnalyzer.get(d.analyzerName) ?? 0) + 1);
|
|
1384
|
+
const affectedRules = d.details?.affectedRules;
|
|
1385
|
+
if (!Array.isArray(affectedRules))
|
|
1386
|
+
continue;
|
|
1387
|
+
const cause = typeof d.details?.cause === 'string' ? d.details.cause : 'unknown';
|
|
1388
|
+
for (const rule of affectedRules) {
|
|
1389
|
+
if (typeof rule !== 'string')
|
|
1390
|
+
continue;
|
|
1391
|
+
let entry = unprovenSitesByRule.get(rule);
|
|
1392
|
+
if (!entry) {
|
|
1393
|
+
entry = { count: 0, causes: new Map() };
|
|
1394
|
+
unprovenSitesByRule.set(rule, entry);
|
|
1395
|
+
}
|
|
1396
|
+
entry.count++;
|
|
1397
|
+
entry.causes.set(cause, (entry.causes.get(cause) ?? 0) + 1);
|
|
1398
|
+
}
|
|
1382
1399
|
}
|
|
1383
|
-
|
|
1400
|
+
// A bare `changed` scope that found no baseline to diff against (an empty
|
|
1401
|
+
// `functions` table) is reported as an uncomputable diff, never as a clean
|
|
1402
|
+
// run. The diagnostic names both possible causes: the index was never
|
|
1403
|
+
// populated, or it was discarded (e.g. after corruption).
|
|
1404
|
+
const noBaselineDiagnostics = changedScopeNoBaseline
|
|
1405
|
+
? [{
|
|
1406
|
+
analyzerName: 'code-index',
|
|
1407
|
+
kind: 'no-baseline',
|
|
1408
|
+
message: 'Cannot determine what changed: the code index holds no baseline to diff against ' +
|
|
1409
|
+
'(no previously indexed files). No index has been built yet, or a prior index was ' +
|
|
1410
|
+
'discarded. Run a full audit to build the baseline, then re-run `changed`.',
|
|
1411
|
+
}]
|
|
1412
|
+
: [];
|
|
1413
|
+
const summary = generateSummary(ordered, files.length, unprovenSitesByAnalyzer, unprovenSitesByRule);
|
|
1384
1414
|
return {
|
|
1385
1415
|
timestamp: new Date(),
|
|
1386
1416
|
summary,
|
|
@@ -1389,6 +1419,7 @@ function buildAuditResult(inputs) {
|
|
|
1389
1419
|
metadata: {
|
|
1390
1420
|
auditDuration: Date.now() - startTime,
|
|
1391
1421
|
auditCpuMs: cpuDurationMs(startCpu),
|
|
1422
|
+
receiverResolutions,
|
|
1392
1423
|
filesAnalyzed: files.length,
|
|
1393
1424
|
...(indexFactsWritten > 0 && { indexFactsWritten, writeIndexFactsMs }),
|
|
1394
1425
|
analyzersRun: analyzers,
|
|
@@ -1397,8 +1428,9 @@ function buildAuditResult(inputs) {
|
|
|
1397
1428
|
scope: scopeResultType,
|
|
1398
1429
|
provenanceResolutionMs: provenanceTiming.totalMs,
|
|
1399
1430
|
...(blastRadius && { blastRadius }),
|
|
1400
|
-
...((zeroFilesDiagnostics.length > 0 || (pipelineDiagnostics?.length ?? 0) > 0 || rejected.length > 0 || lintConfigDiagnostics.length > 0) && {
|
|
1431
|
+
...((noBaselineDiagnostics.length > 0 || zeroFilesDiagnostics.length > 0 || (pipelineDiagnostics?.length ?? 0) > 0 || rejected.length > 0 || lintConfigDiagnostics.length > 0) && {
|
|
1401
1432
|
diagnostics: [
|
|
1433
|
+
...noBaselineDiagnostics,
|
|
1402
1434
|
...zeroFilesDiagnostics,
|
|
1403
1435
|
...(pipelineDiagnostics ?? []),
|
|
1404
1436
|
...lintConfigDiagnostics,
|
|
@@ -1413,7 +1445,6 @@ function buildAuditResult(inputs) {
|
|
|
1413
1445
|
}),
|
|
1414
1446
|
...(baselineMetadata && { baseline: baselineMetadata }),
|
|
1415
1447
|
...(pipelineCoverage && { coverage: pipelineCoverage }),
|
|
1416
|
-
...(routeAttribution && { routeAttribution }),
|
|
1417
1448
|
...(pipelineTableCatalog && { tableCatalog: pipelineTableCatalog }),
|
|
1418
1449
|
...(pipelineStageTiming && { stageTiming: pipelineStageTiming }),
|
|
1419
1450
|
...(thresholdChanges.length > 0 && { thresholdChanges }),
|
|
@@ -1427,6 +1458,8 @@ function buildAuditResult(inputs) {
|
|
|
1427
1458
|
...(pipelineTestCoverage && { testCoverage: pipelineTestCoverage }),
|
|
1428
1459
|
...(pipelineDeadClusters && pipelineDeadClusters.length > 0 && { deadClusters: pipelineDeadClusters }),
|
|
1429
1460
|
...(pipelineSizeDistributions && pipelineSizeDistributions.length > 0 && { sizeDistributions: pipelineSizeDistributions }),
|
|
1461
|
+
...(phaseCandidates.length > 0 && { candidates: phaseCandidates }),
|
|
1462
|
+
...((cacheGc.removedCliVersions.length > 0 || cacheGc.removedProjects.length > 0) && { cacheGc }),
|
|
1430
1463
|
...(collectedFunctions.length > 0 && {
|
|
1431
1464
|
collectedFunctions,
|
|
1432
1465
|
fileToFunctionsMap: Object.fromEntries(fileToFunctionsMap)
|
|
@@ -1488,11 +1521,17 @@ export function createAuditRunner(options = {}) {
|
|
|
1488
1521
|
// `node_modules/.cache/code-auditor`) left by a pre-move build — reported once,
|
|
1489
1522
|
// never deleted (see legacyIndexNotice.ts).
|
|
1490
1523
|
notifyLegacyIndexLocation(root);
|
|
1524
|
+
// Bound the growth of the tool's own fallback cache: superseded pinned-CLI
|
|
1525
|
+
// copies and abandoned project indexes. Process-scoped, never touches a user
|
|
1526
|
+
// CODE_AUDITOR_DATA_DIR or the consuming repo (see cacheGc.ts). The result is
|
|
1527
|
+
// captured (not fire-and-forget) so the audit output states what was collected
|
|
1528
|
+
// — a silent delete of a 132 MB index is exactly the defect K10 forbids.
|
|
1529
|
+
const cacheGc = gcStaleCacheDirsOnce();
|
|
1491
1530
|
// Spec 44 — file accounting accumulator, owned by the run. Threaded through
|
|
1492
1531
|
// discovery (full `all` scope) and the pipeline (stage 1/2) so every touched
|
|
1493
1532
|
// file lands in exactly one terminal state and the balance can be asserted.
|
|
1494
1533
|
const fileAccounting = new FileAccounting();
|
|
1495
|
-
const { files, changedFunctions, skippedExtensions, blastRadius, corpusFiles, scope, isScoped, scopeResultType, } = await discoverAuditFiles(mergedOptions, root, fileAccounting);
|
|
1534
|
+
const { files, changedFunctions, skippedExtensions, blastRadius, corpusFiles, scope, isScoped, scopeResultType, changedScopeNoBaseline, } = await discoverAuditFiles(mergedOptions, root, fileAccounting);
|
|
1496
1535
|
const { collectedFunctions, fileToFunctionsMap } = await collectIndexedFunctions(mergedOptions, files);
|
|
1497
1536
|
// Run analyzers
|
|
1498
1537
|
// Spec 68 §15 — no selection model: the full pipeline always runs. `indexOnly`
|
|
@@ -1510,7 +1549,7 @@ export function createAuditRunner(options = {}) {
|
|
|
1510
1549
|
mergedOptions, root, files, corpusFiles, isScoped, fileAccounting,
|
|
1511
1550
|
styleConsumedFiles, styleContributingFiles, analyzers, provenanceTiming,
|
|
1512
1551
|
});
|
|
1513
|
-
const { analyzerResults, phaseFindings, phaseIncompleteFacts, pipelineCoverage, pipelineTableCatalog, pipelineStageTiming, pipelineSkippedFiles, pipelineUnparsedFiles, pipelineInputPresence, pipelineRuleTiming, pipelineFileAccounting, pipelineDiagnostics, pipelineTestCoverage, pipelineDeadClusters, pipelineSizeDistributions,
|
|
1552
|
+
const { analyzerResults, phaseFindings, phaseIncompleteFacts, phaseReachability, phaseCandidates, receiverResolutions, pipelineCoverage, pipelineTableCatalog, pipelineStageTiming, pipelineSkippedFiles, pipelineUnparsedFiles, pipelineInputPresence, pipelineRuleTiming, pipelineFileAccounting, pipelineDiagnostics, pipelineTestCoverage, pipelineDeadClusters, pipelineSizeDistributions, indexFactsWritten, writeIndexFactsMs, } = pipeline;
|
|
1514
1553
|
// ── Zero-files diagnostic ─────────────────────────────────────────────
|
|
1515
1554
|
// Extracted to runZeroFilesDiagnostics() for testability. Runs against the
|
|
1516
1555
|
// raw analyzerResults before truthiness filtering so the "no result" pass
|
|
@@ -1526,8 +1565,8 @@ export function createAuditRunner(options = {}) {
|
|
|
1526
1565
|
// Normalize the analyzer field on every violation to its result key (the
|
|
1527
1566
|
// single source of truth — see stampAnalyzerFields).
|
|
1528
1567
|
stampAnalyzerFields(orderedAnalyzerResults);
|
|
1529
|
-
// Spec 13 R2 —
|
|
1530
|
-
|
|
1568
|
+
// Spec 13 R2 — reachability scoring & finding reordering (advisory).
|
|
1569
|
+
applyReachabilityRanking(orderedAnalyzerResults, phaseReachability);
|
|
1531
1570
|
// Hook-contract guard: no violation may carry an empty file path, line 0, or
|
|
1532
1571
|
// missing line. A sentinel violation with file:'' broke the Claude Code hook's
|
|
1533
1572
|
// JSON consumer (Spec 15 regression); line:0 from CrossDomainAnalyzer broke it
|
|
@@ -1552,6 +1591,7 @@ export function createAuditRunner(options = {}) {
|
|
|
1552
1591
|
startCpu,
|
|
1553
1592
|
provenanceTiming,
|
|
1554
1593
|
blastRadius,
|
|
1594
|
+
changedScopeNoBaseline,
|
|
1555
1595
|
zeroFilesDiagnostics,
|
|
1556
1596
|
pipelineDiagnostics,
|
|
1557
1597
|
rejected,
|
|
@@ -1559,7 +1599,6 @@ export function createAuditRunner(options = {}) {
|
|
|
1559
1599
|
configPath,
|
|
1560
1600
|
baselineMetadata,
|
|
1561
1601
|
pipelineCoverage,
|
|
1562
|
-
routeAttribution,
|
|
1563
1602
|
pipelineTableCatalog,
|
|
1564
1603
|
pipelineStageTiming,
|
|
1565
1604
|
thresholdChanges,
|
|
@@ -1575,6 +1614,9 @@ export function createAuditRunner(options = {}) {
|
|
|
1575
1614
|
pipelineSizeDistributions,
|
|
1576
1615
|
collectedFunctions,
|
|
1577
1616
|
fileToFunctionsMap,
|
|
1617
|
+
phaseCandidates,
|
|
1618
|
+
receiverResolutions,
|
|
1619
|
+
cacheGc,
|
|
1578
1620
|
});
|
|
1579
1621
|
// Report completion
|
|
1580
1622
|
reportProgress(mergedOptions, {
|
|
@@ -1753,8 +1795,9 @@ export async function resolveFilesScope(options, scopeFiles) {
|
|
|
1753
1795
|
* @param analyzerResults per-analyzer results, keyed by analyzer name
|
|
1754
1796
|
* @param filesAnalyzed total number of files processed this run
|
|
1755
1797
|
* @param unprovenSitesByAnalyzer per-analyzer count of unproven (cannot-fire) sites
|
|
1798
|
+
* @param unprovenSitesByRule per-rule count + cause of unproven (cannot-fire) sites (K9)
|
|
1756
1799
|
*/
|
|
1757
|
-
export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByAnalyzer = new Map()) {
|
|
1800
|
+
export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByAnalyzer = new Map(), unprovenSitesByRule = new Map()) {
|
|
1758
1801
|
let totalViolations = 0;
|
|
1759
1802
|
let criticalIssues = 0;
|
|
1760
1803
|
let severe = 0;
|
|
@@ -1801,6 +1844,14 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1801
1844
|
let unprovenSites = 0;
|
|
1802
1845
|
for (const n of unprovenSitesByAnalyzer.values())
|
|
1803
1846
|
unprovenSites += n;
|
|
1847
|
+
// K9 — materialize the per-rule cannot-fire breakdown as a plain object so
|
|
1848
|
+
// the summary carries it through the JSON/HTML/report surfaces. Keys are the
|
|
1849
|
+
// affected rule ids; `count` is the number of unproven sites that could have
|
|
1850
|
+
// produced a finding under that rule, and `causes` names the emission path.
|
|
1851
|
+
const unprovenSitesByRuleOut = {};
|
|
1852
|
+
for (const [rule, entry] of unprovenSitesByRule) {
|
|
1853
|
+
unprovenSitesByRuleOut[rule] = { count: entry.count, causes: Object.fromEntries(entry.causes) };
|
|
1854
|
+
}
|
|
1804
1855
|
return {
|
|
1805
1856
|
totalFiles: filesAnalyzed,
|
|
1806
1857
|
totalViolations,
|
|
@@ -1811,6 +1862,7 @@ export function generateSummary(analyzerResults, filesAnalyzed, unprovenSitesByA
|
|
|
1811
1862
|
byAnalyzer,
|
|
1812
1863
|
topIssues,
|
|
1813
1864
|
unprovenSites,
|
|
1865
|
+
unprovenSitesByRule: unprovenSitesByRuleOut,
|
|
1814
1866
|
heldOut
|
|
1815
1867
|
};
|
|
1816
1868
|
}
|