code-auditor-mcp 3.1.0 → 3.4.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 +665 -1
- package/README.md +85 -11
- package/dist/__test_tmp__/spec18_test.d.ts +2 -0
- package/dist/__test_tmp__/spec18_test.d.ts.map +1 -0
- package/dist/__test_tmp__/spec18_test.js +5 -0
- package/dist/__test_tmp__/spec18_test.js.map +1 -0
- package/dist/__tests__/fixtures/spec-20/scripts/tool.d.ts +6 -0
- package/dist/__tests__/fixtures/spec-20/scripts/tool.d.ts.map +1 -0
- package/dist/__tests__/fixtures/spec-20/scripts/tool.js +12 -0
- package/dist/__tests__/fixtures/spec-20/scripts/tool.js.map +1 -0
- package/dist/__tests__/fixtures/spec-20/src/demo-module.d.ts +7 -0
- package/dist/__tests__/fixtures/spec-20/src/demo-module.d.ts.map +1 -0
- package/dist/__tests__/fixtures/spec-20/src/demo-module.js +13 -0
- package/dist/__tests__/fixtures/spec-20/src/demo-module.js.map +1 -0
- package/dist/analyzers/analyzerUtils.js +2 -2
- package/dist/analyzers/analyzerUtils.js.map +1 -1
- package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts +1 -1
- package/dist/analyzers/cross-language/APIContractAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/cross-language/APIContractAnalyzer.js +2 -4
- package/dist/analyzers/cross-language/APIContractAnalyzer.js.map +1 -1
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.d.ts +3 -0
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.js +3 -5
- package/dist/analyzers/cross-language/CrossLanguageSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.d.ts.map +1 -1
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js +0 -3
- package/dist/analyzers/cross-language/DependencyGraphBuilder.js.map +1 -1
- package/dist/analyzers/cross-language/SchemaValidator.d.ts +1 -1
- package/dist/analyzers/cross-language/SchemaValidator.d.ts.map +1 -1
- package/dist/analyzers/cross-language/SchemaValidator.js +2 -5
- package/dist/analyzers/cross-language/SchemaValidator.js.map +1 -1
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts +83 -0
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js +611 -0
- package/dist/analyzers/crossDomain/CrossDomainAnalyzer.js.map +1 -0
- package/dist/analyzers/documentationAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/documentationAnalyzer.js +8 -4
- package/dist/analyzers/documentationAnalyzer.js.map +1 -1
- package/dist/analyzers/orm/adapterRegistry.d.ts +41 -0
- package/dist/analyzers/orm/adapterRegistry.d.ts.map +1 -0
- package/dist/analyzers/orm/adapterRegistry.js +73 -0
- package/dist/analyzers/orm/adapterRegistry.js.map +1 -0
- package/dist/analyzers/orm/drizzleAdapter.d.ts +42 -0
- package/dist/analyzers/orm/drizzleAdapter.d.ts.map +1 -0
- package/dist/analyzers/orm/drizzleAdapter.js +166 -0
- package/dist/analyzers/orm/drizzleAdapter.js.map +1 -0
- package/dist/analyzers/orm/index.d.ts +14 -0
- package/dist/analyzers/orm/index.d.ts.map +1 -0
- package/dist/analyzers/orm/index.js +24 -0
- package/dist/analyzers/orm/index.js.map +1 -0
- package/dist/analyzers/orm/prismaAdapter.d.ts +45 -0
- package/dist/analyzers/orm/prismaAdapter.d.ts.map +1 -0
- package/dist/analyzers/orm/prismaAdapter.js +170 -0
- package/dist/analyzers/orm/prismaAdapter.js.map +1 -0
- package/dist/analyzers/orm/types.d.ts +63 -0
- package/dist/analyzers/orm/types.d.ts.map +1 -0
- package/dist/analyzers/orm/types.js +10 -0
- package/dist/analyzers/orm/types.js.map +1 -0
- package/dist/analyzers/provenance.d.ts +133 -0
- package/dist/analyzers/provenance.d.ts.map +1 -0
- package/dist/analyzers/provenance.js +1041 -0
- package/dist/analyzers/provenance.js.map +1 -0
- package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +117 -1
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/ruleRegistry.d.ts +38 -0
- package/dist/analyzers/ruleRegistry.d.ts.map +1 -0
- package/dist/analyzers/ruleRegistry.js +123 -0
- package/dist/analyzers/ruleRegistry.js.map +1 -0
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts +58 -0
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js +445 -0
- package/dist/analyzers/universal/UniversalConventionsAnalyzer.js.map +1 -0
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts +52 -0
- package/dist/analyzers/universal/UniversalDRYAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js +108 -26
- package/dist/analyzers/universal/UniversalDRYAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts +64 -0
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js +259 -103
- package/dist/analyzers/universal/UniversalDataAccessAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js +5 -15
- package/dist/analyzers/universal/UniversalDocumentationAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +10 -10
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +25 -0
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +250 -59
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts +103 -0
- package/dist/analyzers/universal/UniversalStylesAnalyzer.d.ts.map +1 -0
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js +750 -0
- package/dist/analyzers/universal/UniversalStylesAnalyzer.js.map +1 -0
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +483 -3
- package/dist/auditRunner.js.map +1 -1
- package/dist/baseline.d.ts +98 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +184 -0
- package/dist/baseline.js.map +1 -0
- package/dist/churn/churnExtractor.d.ts +32 -0
- package/dist/churn/churnExtractor.d.ts.map +1 -0
- package/dist/churn/churnExtractor.js +261 -0
- package/dist/churn/churnExtractor.js.map +1 -0
- package/dist/cli.js +1215 -11
- package/dist/cli.js.map +1 -1
- package/dist/codeIndexDB-enhanced.js +1 -1
- package/dist/codeIndexDB-enhanced.js.map +1 -1
- package/dist/codeIndexDB.d.ts +101 -0
- package/dist/codeIndexDB.d.ts.map +1 -1
- package/dist/codeIndexDB.js +661 -5
- package/dist/codeIndexDB.js.map +1 -1
- package/dist/config/configLoader.d.ts.map +1 -1
- package/dist/config/configLoader.js +95 -1
- package/dist/config/configLoader.js.map +1 -1
- package/dist/config/defaults.d.ts +72 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +146 -15
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/pathProfiles.d.ts +38 -0
- package/dist/config/pathProfiles.d.ts.map +1 -0
- package/dist/config/pathProfiles.js +47 -0
- package/dist/config/pathProfiles.js.map +1 -0
- package/dist/conventions/conventionMiner.d.ts +63 -0
- package/dist/conventions/conventionMiner.d.ts.map +1 -0
- package/dist/conventions/conventionMiner.js +696 -0
- package/dist/conventions/conventionMiner.js.map +1 -0
- package/dist/coverage/coverageService.d.ts +49 -0
- package/dist/coverage/coverageService.d.ts.map +1 -0
- package/dist/coverage/coverageService.js +117 -0
- package/dist/coverage/coverageService.js.map +1 -0
- package/dist/coverage/istanbulParser.d.ts +84 -0
- package/dist/coverage/istanbulParser.d.ts.map +1 -0
- package/dist/coverage/istanbulParser.js +120 -0
- package/dist/coverage/istanbulParser.js.map +1 -0
- package/dist/coverage/lcovParser.d.ts +40 -0
- package/dist/coverage/lcovParser.d.ts.map +1 -0
- package/dist/coverage/lcovParser.js +168 -0
- package/dist/coverage/lcovParser.js.map +1 -0
- package/dist/fingerprint.d.ts +17 -0
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +42 -0
- package/dist/fingerprint.js.map +1 -1
- package/dist/grammars/tree-sitter-css.wasm +0 -0
- package/dist/graph/blastRadius.d.ts +27 -0
- package/dist/graph/blastRadius.d.ts.map +1 -0
- package/dist/graph/blastRadius.js +150 -0
- package/dist/graph/blastRadius.js.map +1 -0
- package/dist/graph/callGraph.d.ts +78 -0
- package/dist/graph/callGraph.d.ts.map +1 -0
- package/dist/graph/callGraph.js +484 -0
- package/dist/graph/callGraph.js.map +1 -0
- package/dist/graph/importGraph.d.ts +91 -0
- package/dist/graph/importGraph.d.ts.map +1 -0
- package/dist/graph/importGraph.js +602 -0
- package/dist/graph/importGraph.js.map +1 -0
- package/dist/graph/outputFormatter.d.ts +55 -0
- package/dist/graph/outputFormatter.d.ts.map +1 -0
- package/dist/graph/outputFormatter.js +283 -0
- package/dist/graph/outputFormatter.js.map +1 -0
- package/dist/hooks/codex.d.ts +36 -1
- package/dist/hooks/codex.d.ts.map +1 -1
- package/dist/hooks/codex.js +88 -54
- package/dist/hooks/codex.js.map +1 -1
- package/dist/hotspots/hotspotScorer.d.ts +20 -0
- package/dist/hotspots/hotspotScorer.d.ts.map +1 -0
- package/dist/hotspots/hotspotScorer.js +202 -0
- package/dist/hotspots/hotspotScorer.js.map +1 -0
- package/dist/invariants/invariant-rules.schema.json +42 -1
- package/dist/invariants/ruleEngine.d.ts +4 -1
- package/dist/invariants/ruleEngine.d.ts.map +1 -1
- package/dist/invariants/ruleEngine.js +141 -5
- package/dist/invariants/ruleEngine.js.map +1 -1
- package/dist/invariants/ruleValidator.d.ts.map +1 -1
- package/dist/invariants/ruleValidator.js +62 -1
- package/dist/invariants/ruleValidator.js.map +1 -1
- package/dist/invariants/types.d.ts +23 -2
- package/dist/invariants/types.d.ts.map +1 -1
- package/dist/languages/UniversalAnalyzer.d.ts +1 -1
- package/dist/languages/UniversalAnalyzer.d.ts.map +1 -1
- package/dist/languages/UniversalAnalyzer.js +59 -24
- package/dist/languages/UniversalAnalyzer.js.map +1 -1
- package/dist/languages/index.d.ts +1 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +3 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/tree-sitter/TreeSitterCssAdapter.d.ts +59 -0
- package/dist/languages/tree-sitter/TreeSitterCssAdapter.d.ts.map +1 -0
- package/dist/languages/tree-sitter/TreeSitterCssAdapter.js +236 -0
- package/dist/languages/tree-sitter/TreeSitterCssAdapter.js.map +1 -0
- package/dist/languages/tree-sitter/parser.d.ts.map +1 -1
- package/dist/languages/tree-sitter/parser.js +2 -0
- package/dist/languages/tree-sitter/parser.js.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.d.ts.map +1 -1
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js +61 -10
- package/dist/languages/typescript/TreeSitterTypeScriptAdapter.js.map +1 -1
- package/dist/ledger.d.ts +128 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +345 -0
- package/dist/ledger.js.map +1 -0
- package/dist/mcp-tools/projectTasks.d.ts.map +1 -1
- package/dist/mcp-tools/projectTasks.js +9 -14
- package/dist/mcp-tools/projectTasks.js.map +1 -1
- package/dist/mcp.js +0 -0
- package/dist/mcpAuditJobs.d.ts.map +1 -1
- package/dist/mcpAuditJobs.js +3 -0
- package/dist/mcpAuditJobs.js.map +1 -1
- package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
- package/dist/reporting/csvReportGenerator.js +7 -1
- package/dist/reporting/csvReportGenerator.js.map +1 -1
- package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
- package/dist/reporting/htmlReportGenerator.js +5 -1
- package/dist/reporting/htmlReportGenerator.js.map +1 -1
- package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
- package/dist/reporting/jsonReportGenerator.js +10 -2
- package/dist/reporting/jsonReportGenerator.js.map +1 -1
- package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
- package/dist/reporting/sarifReportGenerator.js +17 -17
- package/dist/reporting/sarifReportGenerator.js.map +1 -1
- package/dist/scripts/runBench.d.ts +94 -0
- package/dist/scripts/runBench.d.ts.map +1 -0
- package/dist/scripts/runBench.js +1559 -0
- package/dist/scripts/runBench.js.map +1 -0
- package/dist/search/QueryParser.d.ts.map +1 -1
- package/dist/search/QueryParser.js +51 -4
- package/dist/search/QueryParser.js.map +1 -1
- package/dist/services/CodeMapGenerator.d.ts +33 -0
- package/dist/services/CodeMapGenerator.d.ts.map +1 -1
- package/dist/services/CodeMapGenerator.js +404 -0
- package/dist/services/CodeMapGenerator.js.map +1 -1
- package/dist/styles/normalizer.d.ts +37 -0
- package/dist/styles/normalizer.d.ts.map +1 -0
- package/dist/styles/normalizer.js +301 -0
- package/dist/styles/normalizer.js.map +1 -0
- package/dist/styles/styleExtractor.d.ts +38 -0
- package/dist/styles/styleExtractor.d.ts.map +1 -0
- package/dist/styles/styleExtractor.js +630 -0
- package/dist/styles/styleExtractor.js.map +1 -0
- package/dist/styles/styleIndexer.d.ts +35 -0
- package/dist/styles/styleIndexer.d.ts.map +1 -0
- package/dist/styles/styleIndexer.js +266 -0
- package/dist/styles/styleIndexer.js.map +1 -0
- package/dist/styles/tailwindConfigLoader.d.ts +38 -0
- package/dist/styles/tailwindConfigLoader.d.ts.map +1 -0
- package/dist/styles/tailwindConfigLoader.js +374 -0
- package/dist/styles/tailwindConfigLoader.js.map +1 -0
- package/dist/styles/tailwindExpander.d.ts +38 -0
- package/dist/styles/tailwindExpander.d.ts.map +1 -0
- package/dist/styles/tailwindExpander.js +637 -0
- package/dist/styles/tailwindExpander.js.map +1 -0
- package/dist/styles/types.d.ts +92 -0
- package/dist/styles/types.d.ts.map +1 -0
- package/dist/styles/types.js +10 -0
- package/dist/styles/types.js.map +1 -0
- package/dist/symbols.d.ts +21 -0
- package/dist/symbols.d.ts.map +1 -0
- package/dist/symbols.js +31 -0
- package/dist/symbols.js.map +1 -0
- package/dist/types.d.ts +326 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -5
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/scripts/hook-audit.sh +5 -1
- package/plugin/skills/code-auditor/SKILL.md +51 -0
- package/dist/analyzers/__tests__/fixtures/spec-17/anonymous-callback-map.d.ts +0 -21
- package/dist/analyzers/__tests__/fixtures/spec-17/anonymous-callback-map.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/anonymous-callback-map.js +0 -21
- package/dist/analyzers/__tests__/fixtures/spec-17/anonymous-callback-map.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/barrel-test-migration.d.ts +0 -13
- package/dist/analyzers/__tests__/fixtures/spec-17/barrel-test-migration.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/barrel-test-migration.js +0 -12
- package/dist/analyzers/__tests__/fixtures/spec-17/barrel-test-migration.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/direct-access-allow-config.d.ts +0 -11
- package/dist/analyzers/__tests__/fixtures/spec-17/direct-access-allow-config.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/direct-access-allow-config.js +0 -22
- package/dist/analyzers/__tests__/fixtures/spec-17/direct-access-allow-config.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/exported-undocumented.d.ts +0 -9
- package/dist/analyzers/__tests__/fixtures/spec-17/exported-undocumented.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/exported-undocumented.js +0 -13
- package/dist/analyzers/__tests__/fixtures/spec-17/exported-undocumented.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/for-loop-query.d.ts +0 -13
- package/dist/analyzers/__tests__/fixtures/spec-17/for-loop-query.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/for-loop-query.js +0 -18
- package/dist/analyzers/__tests__/fixtures/spec-17/for-loop-query.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/import-node-builtin.d.ts +0 -10
- package/dist/analyzers/__tests__/fixtures/spec-17/import-node-builtin.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/import-node-builtin.js +0 -16
- package/dist/analyzers/__tests__/fixtures/spec-17/import-node-builtin.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/jsx-event-handler.d.ts +0 -14
- package/dist/analyzers/__tests__/fixtures/spec-17/jsx-event-handler.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/jsx-event-handler.js +0 -18
- package/dist/analyzers/__tests__/fixtures/spec-17/jsx-event-handler.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/nested-loops-query.d.ts +0 -13
- package/dist/analyzers/__tests__/fixtures/spec-17/nested-loops-query.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/nested-loops-query.js +0 -22
- package/dist/analyzers/__tests__/fixtures/spec-17/nested-loops-query.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/nine-line-repeated.d.ts +0 -10
- package/dist/analyzers/__tests__/fixtures/spec-17/nine-line-repeated.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/nine-line-repeated.js +0 -20
- package/dist/analyzers/__tests__/fixtures/spec-17/nine-line-repeated.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/private-methods.d.ts +0 -18
- package/dist/analyzers/__tests__/fixtures/spec-17/private-methods.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/private-methods.js +0 -28
- package/dist/analyzers/__tests__/fixtures/spec-17/private-methods.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/scope-all-config.d.ts +0 -11
- package/dist/analyzers/__tests__/fixtures/spec-17/scope-all-config.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/scope-all-config.js +0 -31
- package/dist/analyzers/__tests__/fixtures/spec-17/scope-all-config.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/sql-tagged-template.d.ts +0 -11
- package/dist/analyzers/__tests__/fixtures/spec-17/sql-tagged-template.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/sql-tagged-template.js +0 -18
- package/dist/analyzers/__tests__/fixtures/spec-17/sql-tagged-template.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/structural-similar-methods.d.ts +0 -13
- package/dist/analyzers/__tests__/fixtures/spec-17/structural-similar-methods.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/structural-similar-methods.js +0 -61
- package/dist/analyzers/__tests__/fixtures/spec-17/structural-similar-methods.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/template-prefix-table.d.ts +0 -10
- package/dist/analyzers/__tests__/fixtures/spec-17/template-prefix-table.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/template-prefix-table.js +0 -15
- package/dist/analyzers/__tests__/fixtures/spec-17/template-prefix-table.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/token-identical-20-lines.d.ts +0 -11
- package/dist/analyzers/__tests__/fixtures/spec-17/token-identical-20-lines.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/token-identical-20-lines.js +0 -49
- package/dist/analyzers/__tests__/fixtures/spec-17/token-identical-20-lines.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/tsx-no-db-usage.d.ts +0 -10
- package/dist/analyzers/__tests__/fixtures/spec-17/tsx-no-db-usage.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/tsx-no-db-usage.js +0 -19
- package/dist/analyzers/__tests__/fixtures/spec-17/tsx-no-db-usage.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/twenty-methods-vs-complex.d.ts +0 -37
- package/dist/analyzers/__tests__/fixtures/spec-17/twenty-methods-vs-complex.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/twenty-methods-vs-complex.js +0 -73
- package/dist/analyzers/__tests__/fixtures/spec-17/twenty-methods-vs-complex.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/unique-method-74-lines.d.ts +0 -12
- package/dist/analyzers/__tests__/fixtures/spec-17/unique-method-74-lines.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/unique-method-74-lines.js +0 -82
- package/dist/analyzers/__tests__/fixtures/spec-17/unique-method-74-lines.js.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/word-the-in-comment.d.ts +0 -10
- package/dist/analyzers/__tests__/fixtures/spec-17/word-the-in-comment.d.ts.map +0 -1
- package/dist/analyzers/__tests__/fixtures/spec-17/word-the-in-comment.js +0 -15
- package/dist/analyzers/__tests__/fixtures/spec-17/word-the-in-comment.js.map +0 -1
- package/dist/analyzers/dataAccessAnalyzer.d.ts +0 -46
- package/dist/analyzers/dataAccessAnalyzer.d.ts.map +0 -1
- package/dist/analyzers/dataAccessAnalyzer.js +0 -474
- package/dist/analyzers/dataAccessAnalyzer.js.map +0 -1
- package/dist/analyzers/dryAnalyzer.d.ts +0 -31
- package/dist/analyzers/dryAnalyzer.d.ts.map +0 -1
- package/dist/analyzers/dryAnalyzer.js +0 -734
- package/dist/analyzers/dryAnalyzer.js.map +0 -1
- package/dist/analyzers/schemaAnalyzer.d.ts +0 -23
- package/dist/analyzers/schemaAnalyzer.d.ts.map +0 -1
- package/dist/analyzers/schemaAnalyzer.js +0 -564
- package/dist/analyzers/schemaAnalyzer.js.map +0 -1
- package/dist/analyzers/solidAnalyzer.d.ts +0 -33
- package/dist/analyzers/solidAnalyzer.d.ts.map +0 -1
- package/dist/analyzers/solidAnalyzer.js +0 -847
- package/dist/analyzers/solidAnalyzer.js.map +0 -1
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec 14 R1, R2 — Call Graph Construction, Centrality, and Risk Ranking
|
|
3
|
+
*
|
|
4
|
+
* Builds a weighted call graph from the `function_calls` table, computes
|
|
5
|
+
* PageRank and betweenness centrality, and produces a risk ranking.
|
|
6
|
+
*
|
|
7
|
+
* All advisory — zero violations. Reports and annotations only.
|
|
8
|
+
*/
|
|
9
|
+
// ── R1 — Call graph construction ───────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Build a weighted call graph from the `function_calls` table.
|
|
12
|
+
*
|
|
13
|
+
* Resolves `callee_name` TEXT → `functions.id` via name join. Edge weight
|
|
14
|
+
* is the count of call sites between the same (caller, callee) pair.
|
|
15
|
+
*/
|
|
16
|
+
export function buildCallGraph(db) {
|
|
17
|
+
const adjacency = new Map();
|
|
18
|
+
const nodeIds = new Set();
|
|
19
|
+
const nodeNames = new Map();
|
|
20
|
+
const nodePaths = new Map();
|
|
21
|
+
// Collect all function IDs, names, file paths
|
|
22
|
+
const allFns = db.prepare('SELECT id, name, file_path FROM functions').all();
|
|
23
|
+
for (const fn of allFns) {
|
|
24
|
+
nodeIds.add(fn.id);
|
|
25
|
+
nodeNames.set(fn.id, fn.name);
|
|
26
|
+
nodePaths.set(fn.id, fn.file_path);
|
|
27
|
+
}
|
|
28
|
+
// Build call graph: group by (caller_id, resolved_callee_id), weight = count
|
|
29
|
+
const callRows = db.prepare(`
|
|
30
|
+
SELECT
|
|
31
|
+
fc.caller_id,
|
|
32
|
+
fc.callee_name,
|
|
33
|
+
f.id AS callee_id
|
|
34
|
+
FROM function_calls fc
|
|
35
|
+
LEFT JOIN functions f ON f.name = fc.callee_name
|
|
36
|
+
`).all();
|
|
37
|
+
let unresolvedCount = 0;
|
|
38
|
+
const totalCalls = callRows.length;
|
|
39
|
+
// Group edge weights: key = "caller_id→callee_id", count occurrences
|
|
40
|
+
const edgeWeights = new Map();
|
|
41
|
+
for (const row of callRows) {
|
|
42
|
+
const callerId = row.caller_id;
|
|
43
|
+
const calleeId = row.callee_id;
|
|
44
|
+
if (calleeId === null || calleeId === undefined) {
|
|
45
|
+
unresolvedCount++;
|
|
46
|
+
// Still add to node set for completeness
|
|
47
|
+
if (!nodeIds.has(callerId)) {
|
|
48
|
+
nodeIds.add(callerId);
|
|
49
|
+
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
// Ensure both nodes are in the graph
|
|
53
|
+
if (!adjacency.has(callerId)) {
|
|
54
|
+
adjacency.set(callerId, new Map());
|
|
55
|
+
}
|
|
56
|
+
if (!adjacency.has(calleeId)) {
|
|
57
|
+
adjacency.set(calleeId, new Map());
|
|
58
|
+
}
|
|
59
|
+
const key = `${callerId}→${calleeId}`;
|
|
60
|
+
edgeWeights.set(key, (edgeWeights.get(key) ?? 0) + 1);
|
|
61
|
+
}
|
|
62
|
+
// Apply edge weights to adjacency
|
|
63
|
+
for (const [key, weight] of edgeWeights) {
|
|
64
|
+
const [callerStr, calleeStr] = key.split('→');
|
|
65
|
+
const callerId = parseInt(callerStr, 10);
|
|
66
|
+
const calleeId = parseInt(calleeStr, 10);
|
|
67
|
+
adjacency.get(callerId).set(calleeId, weight);
|
|
68
|
+
}
|
|
69
|
+
const unresolvedShare = totalCalls > 0 ? unresolvedCount / totalCalls : 0;
|
|
70
|
+
return {
|
|
71
|
+
graph: { adjacency, nodeIds, nodeNames, nodePaths },
|
|
72
|
+
unresolvedCount,
|
|
73
|
+
unresolvedShare,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build a call graph from the persistent `graph_cache` table (fast path).
|
|
78
|
+
*/
|
|
79
|
+
export function buildCallGraphFromCache(db) {
|
|
80
|
+
const adjacency = new Map();
|
|
81
|
+
const nodeIds = new Set();
|
|
82
|
+
const nodeNames = new Map();
|
|
83
|
+
const nodePaths = new Map();
|
|
84
|
+
const allFns = db.prepare('SELECT id, name, file_path FROM functions').all();
|
|
85
|
+
for (const fn of allFns) {
|
|
86
|
+
nodeIds.add(fn.id);
|
|
87
|
+
nodeNames.set(fn.id, fn.name);
|
|
88
|
+
nodePaths.set(fn.id, fn.file_path);
|
|
89
|
+
}
|
|
90
|
+
const rows = db.prepare(`SELECT node_key, neighbor_key, weight FROM graph_cache WHERE graph_type = 'call'`).all();
|
|
91
|
+
for (const row of rows) {
|
|
92
|
+
const callerId = parseInt(row.node_key, 10);
|
|
93
|
+
const calleeId = parseInt(row.neighbor_key, 10);
|
|
94
|
+
if (!adjacency.has(callerId))
|
|
95
|
+
adjacency.set(callerId, new Map());
|
|
96
|
+
if (!adjacency.has(calleeId))
|
|
97
|
+
adjacency.set(calleeId, new Map());
|
|
98
|
+
adjacency.get(callerId).set(calleeId, row.weight);
|
|
99
|
+
}
|
|
100
|
+
// Unresolved: count function_calls where callee_name doesn't match any function
|
|
101
|
+
const resolvedRow = db.prepare(`
|
|
102
|
+
SELECT COUNT(*) as cnt FROM function_calls fc
|
|
103
|
+
JOIN functions f ON f.name = fc.callee_name
|
|
104
|
+
`).get();
|
|
105
|
+
const totalRow = db.prepare('SELECT COUNT(*) as cnt FROM function_calls').get();
|
|
106
|
+
const unresolvedCount = totalRow.cnt - resolvedRow.cnt;
|
|
107
|
+
const unresolvedShare = totalRow.cnt > 0 ? unresolvedCount / totalRow.cnt : 0;
|
|
108
|
+
return {
|
|
109
|
+
graph: { adjacency, nodeIds, nodeNames, nodePaths },
|
|
110
|
+
unresolvedCount,
|
|
111
|
+
unresolvedShare,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Populate `graph_cache` with call and import graph edges.
|
|
116
|
+
* Called after a full sync or scoped sync.
|
|
117
|
+
*/
|
|
118
|
+
export function populateCallGraphCache(db) {
|
|
119
|
+
const txn = db.transaction(() => {
|
|
120
|
+
// Clear existing call cache
|
|
121
|
+
db.prepare("DELETE FROM graph_cache WHERE graph_type = 'call'").run();
|
|
122
|
+
const stmt = db.prepare(`INSERT OR REPLACE INTO graph_cache (graph_type, node_key, neighbor_key, weight)
|
|
123
|
+
VALUES ('call', ?, ?, ?)`);
|
|
124
|
+
// Aggregate call edges with weights
|
|
125
|
+
const rows = db.prepare(`
|
|
126
|
+
SELECT
|
|
127
|
+
fc.caller_id,
|
|
128
|
+
f.id AS callee_id,
|
|
129
|
+
COUNT(*) AS weight
|
|
130
|
+
FROM function_calls fc
|
|
131
|
+
JOIN functions f ON f.name = fc.callee_name
|
|
132
|
+
GROUP BY fc.caller_id, f.id
|
|
133
|
+
`).all();
|
|
134
|
+
for (const row of rows) {
|
|
135
|
+
stmt.run(String(row.caller_id), String(row.callee_id), row.weight);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
txn();
|
|
139
|
+
}
|
|
140
|
+
// ── R2 — PageRank ──────────────────────────────────────────────────────
|
|
141
|
+
/**
|
|
142
|
+
* Compute PageRank on a weighted directed graph.
|
|
143
|
+
*
|
|
144
|
+
* Standard iterative algorithm: damping factor 0.85, convergence 1e-6,
|
|
145
|
+
* max 100 iterations.
|
|
146
|
+
*/
|
|
147
|
+
export function computePageRank(adjacency, nodeIds, damping = 0.85, convergence = 1e-6) {
|
|
148
|
+
const N = nodeIds.size;
|
|
149
|
+
const nodes = [...nodeIds];
|
|
150
|
+
const nodeIndex = new Map();
|
|
151
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
152
|
+
nodeIndex.set(nodes[i], i);
|
|
153
|
+
}
|
|
154
|
+
// Initialize scores to 1/N
|
|
155
|
+
let scores = new Float64Array(N);
|
|
156
|
+
for (let i = 0; i < N; i++)
|
|
157
|
+
scores[i] = 1.0 / N;
|
|
158
|
+
// Pre-compute outbound weights for each node
|
|
159
|
+
const outSum = new Float64Array(N);
|
|
160
|
+
for (const [nodeId, neighbors] of adjacency) {
|
|
161
|
+
const idx = nodeIndex.get(nodeId);
|
|
162
|
+
if (idx === undefined)
|
|
163
|
+
continue;
|
|
164
|
+
let total = 0;
|
|
165
|
+
for (const weight of neighbors.values()) {
|
|
166
|
+
total += weight;
|
|
167
|
+
}
|
|
168
|
+
outSum[idx] = total;
|
|
169
|
+
}
|
|
170
|
+
for (let iter = 0; iter < 100; iter++) {
|
|
171
|
+
const newScores = new Float64Array(N);
|
|
172
|
+
newScores.fill((1 - damping) / N);
|
|
173
|
+
for (const [callerId, neighbors] of adjacency) {
|
|
174
|
+
const callerIdx = nodeIndex.get(callerId);
|
|
175
|
+
if (callerIdx === undefined)
|
|
176
|
+
continue;
|
|
177
|
+
const callerOut = outSum[callerIdx];
|
|
178
|
+
if (callerOut === 0)
|
|
179
|
+
continue;
|
|
180
|
+
const contribution = (damping * scores[callerIdx]) / callerOut;
|
|
181
|
+
for (const [calleeId, weight] of neighbors) {
|
|
182
|
+
const calleeIdx = nodeIndex.get(calleeId);
|
|
183
|
+
if (calleeIdx === undefined)
|
|
184
|
+
continue;
|
|
185
|
+
newScores[calleeIdx] += contribution * weight;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Handle dangling nodes (no outbound edges)
|
|
189
|
+
let danglingSum = 0;
|
|
190
|
+
for (let i = 0; i < N; i++) {
|
|
191
|
+
if (outSum[i] === 0) {
|
|
192
|
+
danglingSum += scores[i];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (danglingSum > 0) {
|
|
196
|
+
const distrib = (damping * danglingSum) / N;
|
|
197
|
+
for (let i = 0; i < N; i++) {
|
|
198
|
+
newScores[i] += distrib;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Check convergence
|
|
202
|
+
let maxDiff = 0;
|
|
203
|
+
for (let i = 0; i < N; i++) {
|
|
204
|
+
const diff = Math.abs(newScores[i] - scores[i]);
|
|
205
|
+
if (diff > maxDiff)
|
|
206
|
+
maxDiff = diff;
|
|
207
|
+
}
|
|
208
|
+
scores = newScores;
|
|
209
|
+
if (maxDiff < convergence)
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
// Convert back to Map<nodeId, score>
|
|
213
|
+
const result = new Map();
|
|
214
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
215
|
+
result.set(nodes[i], scores[i]);
|
|
216
|
+
}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
// ── R2 — Betweenness Centrality ─────────────────────────────────────────
|
|
220
|
+
const BETWEENNESS_EXACT_NODE_CAP = 2000;
|
|
221
|
+
const BETWEENNESS_PIVOT_COUNT = 200;
|
|
222
|
+
/**
|
|
223
|
+
* Compute Brandes betweenness centrality.
|
|
224
|
+
*
|
|
225
|
+
* When `nodeCount <= 2000`, uses exact Brandes.
|
|
226
|
+
* Above that, uses Brandes-Pich pivot sampling with `BETWEENNESS_PIVOT_COUNT` pivots.
|
|
227
|
+
* Returns scores and the number of pivots sampled (0 = exact).
|
|
228
|
+
*/
|
|
229
|
+
export function computeBetweenness(adjacency, nodeIds) {
|
|
230
|
+
const N = nodeIds.size;
|
|
231
|
+
const nodes = [...nodeIds];
|
|
232
|
+
const nodeIndex = new Map();
|
|
233
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
234
|
+
nodeIndex.set(nodes[i], i);
|
|
235
|
+
}
|
|
236
|
+
if (N <= BETWEENNESS_EXACT_NODE_CAP) {
|
|
237
|
+
return { scores: brandesExact(adjacency, nodes, nodeIndex), pivotCount: 0 };
|
|
238
|
+
}
|
|
239
|
+
// Brandes-Pich pivot sampling
|
|
240
|
+
const pivotCount = Math.min(BETWEENNESS_PIVOT_COUNT, N);
|
|
241
|
+
// Deterministic pivot selection: evenly spaced indices
|
|
242
|
+
const pivots = [];
|
|
243
|
+
const step = Math.floor(N / pivotCount);
|
|
244
|
+
for (let i = 0; i < pivotCount; i++) {
|
|
245
|
+
pivots.push(nodes[Math.min(i * step, N - 1)]);
|
|
246
|
+
}
|
|
247
|
+
return { scores: brandesSampled(adjacency, nodes, nodeIndex, pivots), pivotCount };
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Exact Brandes betweenness on all nodes.
|
|
251
|
+
*/
|
|
252
|
+
function brandesExact(adjacency, nodes, nodeIndex) {
|
|
253
|
+
const N = nodes.length;
|
|
254
|
+
const bc = new Float64Array(N);
|
|
255
|
+
for (const s of nodes) {
|
|
256
|
+
const { stack, pred, sigma, dist, delta } = brandesBfs(adjacency, nodeIndex, N, s);
|
|
257
|
+
// Accumulate dependencies (reverse BFS order)
|
|
258
|
+
while (stack.length > 0) {
|
|
259
|
+
const w = stack.pop();
|
|
260
|
+
const wIdx = nodeIndex.get(w);
|
|
261
|
+
for (const v of pred[wIdx]) {
|
|
262
|
+
const vIdx = nodeIndex.get(v);
|
|
263
|
+
const weight = sigma[vIdx] / sigma[wIdx];
|
|
264
|
+
delta[vIdx] += weight * (1 + delta[wIdx]);
|
|
265
|
+
}
|
|
266
|
+
if (w !== s) {
|
|
267
|
+
bc[wIdx] += delta[wIdx];
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Undirected normalization: divide by 2
|
|
272
|
+
// (Brandes for undirected graphs divides by (N-1)(N-2) but we work
|
|
273
|
+
// with a directed call graph, so no normalization is standard.)
|
|
274
|
+
const result = new Map();
|
|
275
|
+
for (let i = 0; i < N; i++) {
|
|
276
|
+
result.set(nodes[i], bc[i]);
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Sampled Brandes-Pich: run exact Brandes from pivot nodes, extrapolate.
|
|
282
|
+
*/
|
|
283
|
+
function brandesSampled(adjacency, nodes, nodeIndex, pivots) {
|
|
284
|
+
const N = nodes.length;
|
|
285
|
+
const bc = new Float64Array(N);
|
|
286
|
+
for (const s of pivots) {
|
|
287
|
+
const { stack, pred, sigma, dist, delta } = brandesBfs(adjacency, nodeIndex, N, s);
|
|
288
|
+
while (stack.length > 0) {
|
|
289
|
+
const w = stack.pop();
|
|
290
|
+
const wIdx = nodeIndex.get(w);
|
|
291
|
+
for (const v of pred[wIdx]) {
|
|
292
|
+
const vIdx = nodeIndex.get(v);
|
|
293
|
+
const weight = sigma[vIdx] / sigma[wIdx];
|
|
294
|
+
delta[vIdx] += weight * (1 + delta[wIdx]);
|
|
295
|
+
}
|
|
296
|
+
if (w !== s) {
|
|
297
|
+
bc[wIdx] += delta[wIdx];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Scale: multiply by N / pivotCount to estimate the full values
|
|
302
|
+
const scale = N / pivots.length;
|
|
303
|
+
const result = new Map();
|
|
304
|
+
for (let i = 0; i < N; i++) {
|
|
305
|
+
result.set(nodes[i], bc[i] * scale);
|
|
306
|
+
}
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Brandes single-source BFS helper.
|
|
311
|
+
* Returns predecessors, sigma (shortest-path counts), distances, deltas, and BFS stack.
|
|
312
|
+
*/
|
|
313
|
+
function brandesBfs(adjacency, nodeIndex, N, source) {
|
|
314
|
+
const stack = [];
|
|
315
|
+
const pred = Array.from({ length: N }, () => []);
|
|
316
|
+
const sigma = new Float64Array(N);
|
|
317
|
+
const dist = new Int32Array(N);
|
|
318
|
+
const delta = new Float64Array(N);
|
|
319
|
+
dist.fill(-1);
|
|
320
|
+
const sIdx = nodeIndex.get(source);
|
|
321
|
+
dist[sIdx] = 0;
|
|
322
|
+
sigma[sIdx] = 1;
|
|
323
|
+
const queue = [source];
|
|
324
|
+
while (queue.length > 0) {
|
|
325
|
+
const v = queue.shift();
|
|
326
|
+
const vIdx = nodeIndex.get(v);
|
|
327
|
+
stack.push(v);
|
|
328
|
+
const neighbors = adjacency.get(v);
|
|
329
|
+
if (!neighbors)
|
|
330
|
+
continue;
|
|
331
|
+
for (const [w, _weight] of neighbors) {
|
|
332
|
+
const wIdx = nodeIndex.get(w);
|
|
333
|
+
if (wIdx === undefined)
|
|
334
|
+
continue;
|
|
335
|
+
// First visit
|
|
336
|
+
if (dist[wIdx] < 0) {
|
|
337
|
+
dist[wIdx] = dist[vIdx] + 1;
|
|
338
|
+
queue.push(w);
|
|
339
|
+
}
|
|
340
|
+
// Edge lies on a shortest path
|
|
341
|
+
if (dist[wIdx] === dist[vIdx] + 1) {
|
|
342
|
+
sigma[wIdx] += sigma[vIdx];
|
|
343
|
+
pred[wIdx].push(v);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return { stack, pred, sigma, dist, delta };
|
|
348
|
+
}
|
|
349
|
+
// ── R2 — Risk ranking ───────────────────────────────────────────────────
|
|
350
|
+
/**
|
|
351
|
+
* Detect whether a function is untested by checking if any transitive caller
|
|
352
|
+
* (depth ≤ 2) resides in a file matching test globs.
|
|
353
|
+
*/
|
|
354
|
+
function detectUntested(db, functionId, adjacency) {
|
|
355
|
+
// Perform a 2-hop BFS in the callers direction (who calls this function)
|
|
356
|
+
const visited = new Set();
|
|
357
|
+
const queue = [{ id: functionId, depth: 0 }];
|
|
358
|
+
visited.add(functionId);
|
|
359
|
+
// Build reverse adjacency (callee → callers) from forward adjacency
|
|
360
|
+
const reverseAdj = new Map();
|
|
361
|
+
for (const [callerId, neighbors] of adjacency) {
|
|
362
|
+
for (const calleeId of neighbors.keys()) {
|
|
363
|
+
if (!reverseAdj.has(calleeId)) {
|
|
364
|
+
reverseAdj.set(calleeId, new Set());
|
|
365
|
+
}
|
|
366
|
+
reverseAdj.get(calleeId).add(callerId);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
while (queue.length > 0) {
|
|
370
|
+
const current = queue.shift();
|
|
371
|
+
if (current.depth > 2)
|
|
372
|
+
continue;
|
|
373
|
+
// Check if this caller's file matches test patterns
|
|
374
|
+
if (current.depth > 0) {
|
|
375
|
+
const fileRow = db.prepare('SELECT file_path FROM functions WHERE id = ?').get(current.id);
|
|
376
|
+
if (fileRow && isTestFile(fileRow.file_path)) {
|
|
377
|
+
return false; // Found a test — NOT untested
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// Follow reverse edges (who calls this node)
|
|
381
|
+
const callers = reverseAdj.get(current.id);
|
|
382
|
+
if (callers) {
|
|
383
|
+
for (const callerId of callers) {
|
|
384
|
+
if (!visited.has(callerId)) {
|
|
385
|
+
visited.add(callerId);
|
|
386
|
+
queue.push({ id: callerId, depth: current.depth + 1 });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return true; // No test caller found — untested
|
|
392
|
+
}
|
|
393
|
+
function isTestFile(filePath) {
|
|
394
|
+
return (filePath.includes('.test.') ||
|
|
395
|
+
filePath.includes('.spec.') ||
|
|
396
|
+
filePath.includes('__tests__') ||
|
|
397
|
+
filePath.includes('/test/') ||
|
|
398
|
+
filePath.includes('/tests/'));
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Compute a risk score for every function.
|
|
402
|
+
*
|
|
403
|
+
* risk = max(pageRank percentile, betweenness percentile)
|
|
404
|
+
* × complexity percentile
|
|
405
|
+
* × (1 + untested) — where untested = 1 if true, 0 otherwise
|
|
406
|
+
*/
|
|
407
|
+
export function computeRisk(db, adjacency, nodeIds, nodeNames, nodePaths) {
|
|
408
|
+
const pageRank = computePageRank(adjacency, nodeIds);
|
|
409
|
+
const { scores: betweenness } = computeBetweenness(adjacency, nodeIds);
|
|
410
|
+
const nodes = [...nodeIds];
|
|
411
|
+
const N = nodes.length;
|
|
412
|
+
if (N === 0)
|
|
413
|
+
return [];
|
|
414
|
+
// Sort nodes by each metric to compute percentiles
|
|
415
|
+
const prSorted = nodes.map(id => ({ id, score: pageRank.get(id) ?? 0 })).sort((a, b) => a.score - b.score);
|
|
416
|
+
const bwSorted = nodes.map(id => ({ id, score: betweenness.get(id) ?? 0 })).sort((a, b) => a.score - b.score);
|
|
417
|
+
const prPercentile = new Map();
|
|
418
|
+
const bwPercentile = new Map();
|
|
419
|
+
for (let i = 0; i < N; i++) {
|
|
420
|
+
prPercentile.set(prSorted[i].id, i / (N - 1));
|
|
421
|
+
bwPercentile.set(bwSorted[i].id, i / (N - 1));
|
|
422
|
+
}
|
|
423
|
+
// Get complexity from DB
|
|
424
|
+
const complexityRows = db.prepare('SELECT id, complexity, name, file_path FROM functions WHERE id IN (' +
|
|
425
|
+
nodes.map(() => '?').join(',') + ')').all(...nodes);
|
|
426
|
+
const complexityMap = new Map();
|
|
427
|
+
for (const row of complexityRows) {
|
|
428
|
+
complexityMap.set(row.id, row.complexity ?? 0);
|
|
429
|
+
}
|
|
430
|
+
// Complexity percentile
|
|
431
|
+
const cxSorted = complexityRows
|
|
432
|
+
.map(r => ({ id: r.id, cx: r.complexity ?? 0 }))
|
|
433
|
+
.sort((a, b) => a.cx - b.cx);
|
|
434
|
+
const cxPercentile = new Map();
|
|
435
|
+
for (let i = 0; i < cxSorted.length; i++) {
|
|
436
|
+
cxPercentile.set(cxSorted[i].id, i / (Math.max(cxSorted.length - 1, 1)));
|
|
437
|
+
}
|
|
438
|
+
// Build risk entries
|
|
439
|
+
const entries = [];
|
|
440
|
+
for (const nodeId of nodes) {
|
|
441
|
+
// Skip unresolved externals (IDs that appear only as callees but aren't in functions table)
|
|
442
|
+
const name = nodeNames.get(nodeId);
|
|
443
|
+
const filePath = nodePaths.get(nodeId);
|
|
444
|
+
if (!name || !filePath)
|
|
445
|
+
continue;
|
|
446
|
+
const pr = prPercentile.get(nodeId) ?? 0;
|
|
447
|
+
const bw = bwPercentile.get(nodeId) ?? 0;
|
|
448
|
+
const cx = cxPercentile.get(nodeId) ?? 0;
|
|
449
|
+
const untested = detectUntested(db, nodeId, adjacency);
|
|
450
|
+
const risk = Math.max(pr, bw) * cx * (1 + (untested ? 1 : 0));
|
|
451
|
+
entries.push({
|
|
452
|
+
functionName: name,
|
|
453
|
+
filePath,
|
|
454
|
+
pageRankPercentile: pr,
|
|
455
|
+
betweennessPercentile: bw,
|
|
456
|
+
complexityPercentile: cx,
|
|
457
|
+
untested,
|
|
458
|
+
riskScore: risk,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
// Sort by risk descending
|
|
462
|
+
entries.sort((a, b) => b.riskScore - a.riskScore);
|
|
463
|
+
return entries;
|
|
464
|
+
}
|
|
465
|
+
// ── Graph statistics ────────────────────────────────────────────────────
|
|
466
|
+
export function getGraphStats(db) {
|
|
467
|
+
const callRows = db.prepare(`SELECT COUNT(*) as cnt FROM graph_cache WHERE graph_type = 'call'`).get();
|
|
468
|
+
const importRows = db.prepare(`SELECT COUNT(*) as cnt FROM graph_cache WHERE graph_type = 'import'`).get();
|
|
469
|
+
const callNodes = db.prepare("SELECT COUNT(DISTINCT node_key) as cnt FROM graph_cache WHERE graph_type = 'call'").get().cnt;
|
|
470
|
+
const importNodes = db.prepare("SELECT COUNT(DISTINCT node_key) as cnt FROM graph_cache WHERE graph_type = 'import'").get().cnt;
|
|
471
|
+
const totalCalls = db.prepare('SELECT COUNT(*) as cnt FROM function_calls').get().cnt;
|
|
472
|
+
const resolvedCalls = db.prepare('SELECT COUNT(*) as cnt FROM function_calls fc JOIN functions f ON f.name = fc.callee_name').get().cnt;
|
|
473
|
+
const unresolvedCalls = totalCalls - resolvedCalls;
|
|
474
|
+
const unresolvedShare = totalCalls > 0 ? unresolvedCalls / totalCalls : 0;
|
|
475
|
+
return {
|
|
476
|
+
callNodes,
|
|
477
|
+
callEdges: callRows.cnt,
|
|
478
|
+
unresolvedCalls,
|
|
479
|
+
unresolvedShare,
|
|
480
|
+
importNodes,
|
|
481
|
+
importEdges: importRows.cnt,
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
//# sourceMappingURL=callGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callGraph.js","sourceRoot":"","sources":["../../src/graph/callGraph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec 14 R3, R4 — Import Graph, Community Detection, and Martin Metrics
|
|
3
|
+
*
|
|
4
|
+
* Builds a file-level import graph from `function_dependencies`, runs Louvain
|
|
5
|
+
* community detection, computes directory purity vs community structure, and
|
|
6
|
+
* calculates Martin instability/abstractness metrics.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT (R4 abstractness gate): The `functions` entity_type column stores
|
|
9
|
+
* only 'function' and 'component' — NOT type/interface declarations. Abstractness (A)
|
|
10
|
+
* is computed from `is_exported` rows using a per-file AST scan for export type/interface
|
|
11
|
+
* declarations. Without this, A = 0 everywhere (dead path).
|
|
12
|
+
*
|
|
13
|
+
* All advisory — zero violations. Reports and annotations only.
|
|
14
|
+
*/
|
|
15
|
+
import type Database from 'better-sqlite3';
|
|
16
|
+
import type { DirectoryPurity, MartinEntry } from '../types.js';
|
|
17
|
+
export interface ImportGraph {
|
|
18
|
+
/** Adjacency: filePath → (neighborFilePath → edgeWeight) */
|
|
19
|
+
adjacency: Map<string, Map<string, number>>;
|
|
20
|
+
/** Set of all file paths in the graph */
|
|
21
|
+
filePaths: Set<string>;
|
|
22
|
+
}
|
|
23
|
+
export interface CommunityResult {
|
|
24
|
+
/** filePath → community ID */
|
|
25
|
+
communities: Map<string, number>;
|
|
26
|
+
/** Number of communities detected */
|
|
27
|
+
communityCount: number;
|
|
28
|
+
/** Final modularity score */
|
|
29
|
+
modularity: number;
|
|
30
|
+
}
|
|
31
|
+
export interface PurityResult {
|
|
32
|
+
directoryPurities: DirectoryPurity[];
|
|
33
|
+
splitCandidates: Array<{
|
|
34
|
+
directory: string;
|
|
35
|
+
communities: number[];
|
|
36
|
+
fileCounts: number[];
|
|
37
|
+
}>;
|
|
38
|
+
mergeCandidates: Array<{
|
|
39
|
+
directories: string[];
|
|
40
|
+
community: number;
|
|
41
|
+
fileCount: number;
|
|
42
|
+
}>;
|
|
43
|
+
agreementScore: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build a file-level import graph by aggregating `function_dependencies`
|
|
47
|
+
* joined with `functions.file_path`.
|
|
48
|
+
*
|
|
49
|
+
* Edge weight = count of distinct dependency symbols between a file pair.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildImportGraph(db: Database.Database): ImportGraph;
|
|
52
|
+
/**
|
|
53
|
+
* Populate `graph_cache` with import graph edges.
|
|
54
|
+
*/
|
|
55
|
+
export declare function populateImportGraphCache(db: Database.Database): void;
|
|
56
|
+
/**
|
|
57
|
+
* Build an import graph from the persistent `graph_cache` table (fast path).
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildImportGraphFromCache(db: Database.Database): ImportGraph;
|
|
60
|
+
/**
|
|
61
|
+
* Louvain community detection on weighted undirected graph.
|
|
62
|
+
*
|
|
63
|
+
* Standard two-phase algorithm:
|
|
64
|
+
* Phase 1: Greedy modularity optimization (move nodes between communities)
|
|
65
|
+
* Phase 2: Community aggregation (build super-graph)
|
|
66
|
+
* Repeat until modularity gain < threshold.
|
|
67
|
+
*/
|
|
68
|
+
export declare function detectCommunities(adjacency: Map<string, Map<string, number>>, filePaths: Set<string>): CommunityResult;
|
|
69
|
+
/**
|
|
70
|
+
* Compute directory purity against detected communities.
|
|
71
|
+
*
|
|
72
|
+
* For each directory, compute: share of its files in the plurality community.
|
|
73
|
+
* Detects split candidates (directories spanning ≥2 communities) and
|
|
74
|
+
* merge candidates (one community dominating ≥2 directories).
|
|
75
|
+
*/
|
|
76
|
+
export declare function computeDirectoryPurity(communities: Map<string, number>, filePaths: Set<string>): PurityResult;
|
|
77
|
+
/**
|
|
78
|
+
* Compute Martin metrics per directory (treated as package).
|
|
79
|
+
*
|
|
80
|
+
* Ce = efferent couplings: distinct directories this directory imports from
|
|
81
|
+
* Ca = afferent couplings: distinct directories that import this directory
|
|
82
|
+
* I = Ce / (Ca + Ce) — instability (0 if both zero)
|
|
83
|
+
* A = abstractness: exported type/interface declarations ÷ total exported symbols
|
|
84
|
+
* D = |A + I − 1| — distance from main sequence
|
|
85
|
+
*
|
|
86
|
+
* IMPORTANT: Abstractness computation uses an AST scan for export type/interface
|
|
87
|
+
* declarations because the `functions` table does not index type/interface entities.
|
|
88
|
+
* Uses a lightweight file-content scan.
|
|
89
|
+
*/
|
|
90
|
+
export declare function computeMartinMetrics(db: Database.Database, importGraph: ImportGraph): MartinEntry[];
|
|
91
|
+
//# sourceMappingURL=importGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"importGraph.d.ts","sourceRoot":"","sources":["../../src/graph/importGraph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIhE,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,yCAAyC;IACzC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,eAAe,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC3F,eAAe,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxF,cAAc,EAAE,MAAM,CAAC;CACxB;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,WAAW,CAwEnE;AAoGD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAkBpE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,WAAW,CAgB5E;AAID;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC3C,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,eAAe,CAgMjB;AAoCD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,YAAY,CA6Fd;AAUD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,WAAW,GACvB,WAAW,EAAE,CA4Gf"}
|