driftdetect-core 0.5.0 → 0.6.1
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/dist/boundaries/types.d.ts +1 -1
- package/dist/boundaries/types.d.ts.map +1 -1
- package/dist/call-graph/analysis/graph-builder.d.ts.map +1 -1
- package/dist/call-graph/analysis/graph-builder.js +1 -0
- package/dist/call-graph/analysis/graph-builder.js.map +1 -1
- package/dist/call-graph/extractors/go-data-access-extractor.d.ts +80 -0
- package/dist/call-graph/extractors/go-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/go-data-access-extractor.js +457 -0
- package/dist/call-graph/extractors/go-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/go-extractor.d.ts +103 -0
- package/dist/call-graph/extractors/go-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/go-extractor.js +509 -0
- package/dist/call-graph/extractors/go-extractor.js.map +1 -0
- package/dist/call-graph/extractors/go-hybrid-extractor.d.ts +97 -0
- package/dist/call-graph/extractors/go-hybrid-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/go-hybrid-extractor.js +496 -0
- package/dist/call-graph/extractors/go-hybrid-extractor.js.map +1 -0
- package/dist/call-graph/extractors/regex/go-regex.d.ts +51 -0
- package/dist/call-graph/extractors/regex/go-regex.d.ts.map +1 -0
- package/dist/call-graph/extractors/regex/go-regex.js +435 -0
- package/dist/call-graph/extractors/regex/go-regex.js.map +1 -0
- package/dist/call-graph/extractors/regex/index.d.ts +1 -0
- package/dist/call-graph/extractors/regex/index.d.ts.map +1 -1
- package/dist/call-graph/extractors/regex/index.js +8 -0
- package/dist/call-graph/extractors/regex/index.js.map +1 -1
- package/dist/call-graph/index.d.ts +3 -0
- package/dist/call-graph/index.d.ts.map +1 -1
- package/dist/call-graph/index.js +5 -0
- package/dist/call-graph/index.js.map +1 -1
- package/dist/call-graph/types.d.ts +1 -1
- package/dist/call-graph/types.d.ts.map +1 -1
- package/dist/constraints/extraction/constraint-synthesizer.d.ts +72 -0
- package/dist/constraints/extraction/constraint-synthesizer.d.ts.map +1 -0
- package/dist/constraints/extraction/constraint-synthesizer.js +336 -0
- package/dist/constraints/extraction/constraint-synthesizer.js.map +1 -0
- package/dist/constraints/extraction/index.d.ts +10 -0
- package/dist/constraints/extraction/index.d.ts.map +1 -0
- package/dist/constraints/extraction/index.js +10 -0
- package/dist/constraints/extraction/index.js.map +1 -0
- package/dist/constraints/extraction/invariant-detector.d.ts +109 -0
- package/dist/constraints/extraction/invariant-detector.d.ts.map +1 -0
- package/dist/constraints/extraction/invariant-detector.js +979 -0
- package/dist/constraints/extraction/invariant-detector.js.map +1 -0
- package/dist/constraints/index.d.ts +15 -0
- package/dist/constraints/index.d.ts.map +1 -0
- package/dist/constraints/index.js +16 -0
- package/dist/constraints/index.js.map +1 -0
- package/dist/constraints/store/constraint-store.d.ts +110 -0
- package/dist/constraints/store/constraint-store.d.ts.map +1 -0
- package/dist/constraints/store/constraint-store.js +584 -0
- package/dist/constraints/store/constraint-store.js.map +1 -0
- package/dist/constraints/types.d.ts +605 -0
- package/dist/constraints/types.d.ts.map +1 -0
- package/dist/constraints/types.js +57 -0
- package/dist/constraints/types.js.map +1 -0
- package/dist/constraints/verification/constraint-verifier.d.ts +100 -0
- package/dist/constraints/verification/constraint-verifier.d.ts.map +1 -0
- package/dist/constraints/verification/constraint-verifier.js +638 -0
- package/dist/constraints/verification/constraint-verifier.js.map +1 -0
- package/dist/constraints/verification/index.d.ts +8 -0
- package/dist/constraints/verification/index.d.ts.map +1 -0
- package/dist/constraints/verification/index.js +8 -0
- package/dist/constraints/verification/index.js.map +1 -0
- package/dist/decisions/analyzer/decision-mining-analyzer.d.ts +121 -0
- package/dist/decisions/analyzer/decision-mining-analyzer.d.ts.map +1 -0
- package/dist/decisions/analyzer/decision-mining-analyzer.js +904 -0
- package/dist/decisions/analyzer/decision-mining-analyzer.js.map +1 -0
- package/dist/decisions/analyzer/index.d.ts +5 -0
- package/dist/decisions/analyzer/index.d.ts.map +1 -0
- package/dist/decisions/analyzer/index.js +5 -0
- package/dist/decisions/analyzer/index.js.map +1 -0
- package/dist/decisions/extractors/base-commit-extractor.d.ts +104 -0
- package/dist/decisions/extractors/base-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/base-commit-extractor.js +305 -0
- package/dist/decisions/extractors/base-commit-extractor.js.map +1 -0
- package/dist/decisions/extractors/csharp-commit-extractor.d.ts +18 -0
- package/dist/decisions/extractors/csharp-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/csharp-commit-extractor.js +281 -0
- package/dist/decisions/extractors/csharp-commit-extractor.js.map +1 -0
- package/dist/decisions/extractors/index.d.ts +31 -0
- package/dist/decisions/extractors/index.d.ts.map +1 -0
- package/dist/decisions/extractors/index.js +63 -0
- package/dist/decisions/extractors/index.js.map +1 -0
- package/dist/decisions/extractors/java-commit-extractor.d.ts +18 -0
- package/dist/decisions/extractors/java-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/java-commit-extractor.js +248 -0
- package/dist/decisions/extractors/java-commit-extractor.js.map +1 -0
- package/dist/decisions/extractors/php-commit-extractor.d.ts +18 -0
- package/dist/decisions/extractors/php-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/php-commit-extractor.js +280 -0
- package/dist/decisions/extractors/php-commit-extractor.js.map +1 -0
- package/dist/decisions/extractors/python-commit-extractor.d.ts +18 -0
- package/dist/decisions/extractors/python-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/python-commit-extractor.js +248 -0
- package/dist/decisions/extractors/python-commit-extractor.js.map +1 -0
- package/dist/decisions/extractors/typescript-commit-extractor.d.ts +37 -0
- package/dist/decisions/extractors/typescript-commit-extractor.d.ts.map +1 -0
- package/dist/decisions/extractors/typescript-commit-extractor.js +229 -0
- package/dist/decisions/extractors/typescript-commit-extractor.js.map +1 -0
- package/dist/decisions/git/commit-parser.d.ts +58 -0
- package/dist/decisions/git/commit-parser.d.ts.map +1 -0
- package/dist/decisions/git/commit-parser.js +344 -0
- package/dist/decisions/git/commit-parser.js.map +1 -0
- package/dist/decisions/git/diff-analyzer.d.ts +30 -0
- package/dist/decisions/git/diff-analyzer.d.ts.map +1 -0
- package/dist/decisions/git/diff-analyzer.js +492 -0
- package/dist/decisions/git/diff-analyzer.js.map +1 -0
- package/dist/decisions/git/git-walker.d.ts +64 -0
- package/dist/decisions/git/git-walker.d.ts.map +1 -0
- package/dist/decisions/git/git-walker.js +441 -0
- package/dist/decisions/git/git-walker.js.map +1 -0
- package/dist/decisions/git/index.d.ts +11 -0
- package/dist/decisions/git/index.d.ts.map +1 -0
- package/dist/decisions/git/index.js +13 -0
- package/dist/decisions/git/index.js.map +1 -0
- package/dist/decisions/git/types.d.ts +223 -0
- package/dist/decisions/git/types.d.ts.map +1 -0
- package/dist/decisions/git/types.js +7 -0
- package/dist/decisions/git/types.js.map +1 -0
- package/dist/decisions/index.d.ts +27 -0
- package/dist/decisions/index.d.ts.map +1 -0
- package/dist/decisions/index.js +45 -0
- package/dist/decisions/index.js.map +1 -0
- package/dist/decisions/types.d.ts +530 -0
- package/dist/decisions/types.d.ts.map +1 -0
- package/dist/decisions/types.js +8 -0
- package/dist/decisions/types.js.map +1 -0
- package/dist/go/go-analyzer.d.ts +203 -0
- package/dist/go/go-analyzer.d.ts.map +1 -0
- package/dist/go/go-analyzer.js +509 -0
- package/dist/go/go-analyzer.js.map +1 -0
- package/dist/go/index.d.ts +7 -0
- package/dist/go/index.d.ts.map +1 -0
- package/dist/go/index.js +8 -0
- package/dist/go/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -1
- package/dist/parsers/tree-sitter/go-loader.d.ts +50 -0
- package/dist/parsers/tree-sitter/go-loader.d.ts.map +1 -0
- package/dist/parsers/tree-sitter/go-loader.js +161 -0
- package/dist/parsers/tree-sitter/go-loader.js.map +1 -0
- package/dist/parsers/tree-sitter/tree-sitter-go-parser.d.ts +250 -0
- package/dist/parsers/tree-sitter/tree-sitter-go-parser.d.ts.map +1 -0
- package/dist/parsers/tree-sitter/tree-sitter-go-parser.js +707 -0
- package/dist/parsers/tree-sitter/tree-sitter-go-parser.js.map +1 -0
- package/dist/parsers/types.d.ts +1 -1
- package/dist/parsers/types.d.ts.map +1 -1
- package/dist/simulation/approach-generator.d.ts +73 -0
- package/dist/simulation/approach-generator.d.ts.map +1 -0
- package/dist/simulation/approach-generator.js +371 -0
- package/dist/simulation/approach-generator.js.map +1 -0
- package/dist/simulation/index.d.ts +14 -0
- package/dist/simulation/index.d.ts.map +1 -0
- package/dist/simulation/index.js +19 -0
- package/dist/simulation/index.js.map +1 -0
- package/dist/simulation/language-strategies/csharp-strategies.d.ts +17 -0
- package/dist/simulation/language-strategies/csharp-strategies.d.ts.map +1 -0
- package/dist/simulation/language-strategies/csharp-strategies.js +118 -0
- package/dist/simulation/language-strategies/csharp-strategies.js.map +1 -0
- package/dist/simulation/language-strategies/index.d.ts +41 -0
- package/dist/simulation/language-strategies/index.d.ts.map +1 -0
- package/dist/simulation/language-strategies/index.js +92 -0
- package/dist/simulation/language-strategies/index.js.map +1 -0
- package/dist/simulation/language-strategies/java-strategies.d.ts +17 -0
- package/dist/simulation/language-strategies/java-strategies.d.ts.map +1 -0
- package/dist/simulation/language-strategies/java-strategies.js +119 -0
- package/dist/simulation/language-strategies/java-strategies.js.map +1 -0
- package/dist/simulation/language-strategies/php-strategies.d.ts +17 -0
- package/dist/simulation/language-strategies/php-strategies.d.ts.map +1 -0
- package/dist/simulation/language-strategies/php-strategies.js +129 -0
- package/dist/simulation/language-strategies/php-strategies.js.map +1 -0
- package/dist/simulation/language-strategies/python-strategies.d.ts +17 -0
- package/dist/simulation/language-strategies/python-strategies.d.ts.map +1 -0
- package/dist/simulation/language-strategies/python-strategies.js +208 -0
- package/dist/simulation/language-strategies/python-strategies.js.map +1 -0
- package/dist/simulation/language-strategies/types.d.ts +67 -0
- package/dist/simulation/language-strategies/types.d.ts.map +1 -0
- package/dist/simulation/language-strategies/types.js +23 -0
- package/dist/simulation/language-strategies/types.js.map +1 -0
- package/dist/simulation/language-strategies/typescript-strategies.d.ts +17 -0
- package/dist/simulation/language-strategies/typescript-strategies.d.ts.map +1 -0
- package/dist/simulation/language-strategies/typescript-strategies.js +251 -0
- package/dist/simulation/language-strategies/typescript-strategies.js.map +1 -0
- package/dist/simulation/scorers/friction-scorer.d.ts +45 -0
- package/dist/simulation/scorers/friction-scorer.d.ts.map +1 -0
- package/dist/simulation/scorers/friction-scorer.js +336 -0
- package/dist/simulation/scorers/friction-scorer.js.map +1 -0
- package/dist/simulation/scorers/impact-scorer.d.ts +56 -0
- package/dist/simulation/scorers/impact-scorer.d.ts.map +1 -0
- package/dist/simulation/scorers/impact-scorer.js +273 -0
- package/dist/simulation/scorers/impact-scorer.js.map +1 -0
- package/dist/simulation/scorers/index.d.ts +12 -0
- package/dist/simulation/scorers/index.d.ts.map +1 -0
- package/dist/simulation/scorers/index.js +12 -0
- package/dist/simulation/scorers/index.js.map +1 -0
- package/dist/simulation/scorers/pattern-alignment-scorer.d.ts +83 -0
- package/dist/simulation/scorers/pattern-alignment-scorer.d.ts.map +1 -0
- package/dist/simulation/scorers/pattern-alignment-scorer.js +367 -0
- package/dist/simulation/scorers/pattern-alignment-scorer.js.map +1 -0
- package/dist/simulation/scorers/security-scorer.d.ts +63 -0
- package/dist/simulation/scorers/security-scorer.d.ts.map +1 -0
- package/dist/simulation/scorers/security-scorer.js +346 -0
- package/dist/simulation/scorers/security-scorer.js.map +1 -0
- package/dist/simulation/simulation-engine.d.ts +89 -0
- package/dist/simulation/simulation-engine.d.ts.map +1 -0
- package/dist/simulation/simulation-engine.js +480 -0
- package/dist/simulation/simulation-engine.js.map +1 -0
- package/dist/simulation/types.d.ts +200 -0
- package/dist/simulation/types.d.ts.map +1 -0
- package/dist/simulation/types.js +23 -0
- package/dist/simulation/types.js.map +1 -0
- package/dist/speculative/approach-generator.d.ts +2 -0
- package/dist/speculative/approach-generator.d.ts.map +1 -0
- package/dist/speculative/approach-generator.js +2 -0
- package/dist/speculative/approach-generator.js.map +1 -0
- package/dist/speculative/templates/types.d.ts +133 -0
- package/dist/speculative/templates/types.d.ts.map +1 -0
- package/dist/speculative/templates/types.js +208 -0
- package/dist/speculative/templates/types.js.map +1 -0
- package/dist/speculative/types.d.ts +523 -0
- package/dist/speculative/types.d.ts.map +1 -0
- package/dist/speculative/types.js +71 -0
- package/dist/speculative/types.js.map +1 -0
- package/dist/test-topology/extractors/base-test-extractor.d.ts +1 -1
- package/dist/test-topology/extractors/base-test-extractor.d.ts.map +1 -1
- package/dist/test-topology/extractors/base-test-extractor.js.map +1 -1
- package/dist/test-topology/extractors/go-test-extractor.d.ts +33 -0
- package/dist/test-topology/extractors/go-test-extractor.d.ts.map +1 -0
- package/dist/test-topology/extractors/go-test-extractor.js +436 -0
- package/dist/test-topology/extractors/go-test-extractor.js.map +1 -0
- package/dist/test-topology/extractors/index.d.ts +1 -0
- package/dist/test-topology/extractors/index.d.ts.map +1 -1
- package/dist/test-topology/extractors/index.js +1 -0
- package/dist/test-topology/extractors/index.js.map +1 -1
- package/dist/test-topology/extractors/regex/go-test-regex.d.ts +62 -0
- package/dist/test-topology/extractors/regex/go-test-regex.d.ts.map +1 -0
- package/dist/test-topology/extractors/regex/go-test-regex.js +528 -0
- package/dist/test-topology/extractors/regex/go-test-regex.js.map +1 -0
- package/dist/test-topology/extractors/regex/index.d.ts +1 -0
- package/dist/test-topology/extractors/regex/index.d.ts.map +1 -1
- package/dist/test-topology/extractors/regex/index.js +4 -0
- package/dist/test-topology/extractors/regex/index.js.map +1 -1
- package/dist/test-topology/hybrid-test-topology-analyzer.d.ts.map +1 -1
- package/dist/test-topology/hybrid-test-topology-analyzer.js +1 -0
- package/dist/test-topology/hybrid-test-topology-analyzer.js.map +1 -1
- package/dist/test-topology/test-topology-analyzer.d.ts.map +1 -1
- package/dist/test-topology/test-topology-analyzer.js +1 -0
- package/dist/test-topology/test-topology-analyzer.js.map +1 -1
- package/dist/test-topology/types.d.ts +2 -2
- package/dist/test-topology/types.d.ts.map +1 -1
- package/dist/unified-provider/matching/database-sql-matcher.d.ts +42 -0
- package/dist/unified-provider/matching/database-sql-matcher.d.ts.map +1 -0
- package/dist/unified-provider/matching/database-sql-matcher.js +282 -0
- package/dist/unified-provider/matching/database-sql-matcher.js.map +1 -0
- package/dist/unified-provider/matching/gorm-matcher.d.ts +41 -0
- package/dist/unified-provider/matching/gorm-matcher.d.ts.map +1 -0
- package/dist/unified-provider/matching/gorm-matcher.js +222 -0
- package/dist/unified-provider/matching/gorm-matcher.js.map +1 -0
- package/dist/unified-provider/matching/index.d.ts +3 -0
- package/dist/unified-provider/matching/index.d.ts.map +1 -1
- package/dist/unified-provider/matching/index.js +4 -0
- package/dist/unified-provider/matching/index.js.map +1 -1
- package/dist/unified-provider/matching/matcher-registry.d.ts.map +1 -1
- package/dist/unified-provider/matching/matcher-registry.js +7 -0
- package/dist/unified-provider/matching/matcher-registry.js.map +1 -1
- package/dist/unified-provider/matching/sqlx-matcher.d.ts +40 -0
- package/dist/unified-provider/matching/sqlx-matcher.d.ts.map +1 -0
- package/dist/unified-provider/matching/sqlx-matcher.js +214 -0
- package/dist/unified-provider/matching/sqlx-matcher.js.map +1 -0
- package/dist/unified-provider/normalization/go-normalizer.d.ts +62 -0
- package/dist/unified-provider/normalization/go-normalizer.d.ts.map +1 -0
- package/dist/unified-provider/normalization/go-normalizer.js +608 -0
- package/dist/unified-provider/normalization/go-normalizer.js.map +1 -0
- package/dist/unified-provider/normalization/index.d.ts +1 -0
- package/dist/unified-provider/normalization/index.d.ts.map +1 -1
- package/dist/unified-provider/normalization/index.js +6 -1
- package/dist/unified-provider/normalization/index.js.map +1 -1
- package/dist/unified-provider/types.d.ts +1 -1
- package/dist/unified-provider/types.d.ts.map +1 -1
- package/dist/wpf/extractors/binding-error-detector.d.ts +75 -0
- package/dist/wpf/extractors/binding-error-detector.d.ts.map +1 -0
- package/dist/wpf/extractors/binding-error-detector.js +290 -0
- package/dist/wpf/extractors/binding-error-detector.js.map +1 -0
- package/dist/wpf/extractors/code-behind-linker.d.ts +70 -0
- package/dist/wpf/extractors/code-behind-linker.d.ts.map +1 -0
- package/dist/wpf/extractors/code-behind-linker.js +172 -0
- package/dist/wpf/extractors/code-behind-linker.js.map +1 -0
- package/dist/wpf/extractors/dependency-property-extractor.d.ts +61 -0
- package/dist/wpf/extractors/dependency-property-extractor.d.ts.map +1 -0
- package/dist/wpf/extractors/dependency-property-extractor.js +201 -0
- package/dist/wpf/extractors/dependency-property-extractor.js.map +1 -0
- package/dist/wpf/extractors/regex/viewmodel-regex.d.ts +82 -0
- package/dist/wpf/extractors/regex/viewmodel-regex.d.ts.map +1 -0
- package/dist/wpf/extractors/regex/viewmodel-regex.js +412 -0
- package/dist/wpf/extractors/regex/viewmodel-regex.js.map +1 -0
- package/dist/wpf/extractors/regex/xaml-regex.d.ts +77 -0
- package/dist/wpf/extractors/regex/xaml-regex.d.ts.map +1 -0
- package/dist/wpf/extractors/regex/xaml-regex.js +353 -0
- package/dist/wpf/extractors/regex/xaml-regex.js.map +1 -0
- package/dist/wpf/extractors/resource-dictionary-parser.d.ts +103 -0
- package/dist/wpf/extractors/resource-dictionary-parser.d.ts.map +1 -0
- package/dist/wpf/extractors/resource-dictionary-parser.js +296 -0
- package/dist/wpf/extractors/resource-dictionary-parser.js.map +1 -0
- package/dist/wpf/extractors/value-converter-extractor.d.ts +128 -0
- package/dist/wpf/extractors/value-converter-extractor.d.ts.map +1 -0
- package/dist/wpf/extractors/value-converter-extractor.js +312 -0
- package/dist/wpf/extractors/value-converter-extractor.js.map +1 -0
- package/dist/wpf/extractors/viewmodel-hybrid-extractor.d.ts +104 -0
- package/dist/wpf/extractors/viewmodel-hybrid-extractor.d.ts.map +1 -0
- package/dist/wpf/extractors/viewmodel-hybrid-extractor.js +513 -0
- package/dist/wpf/extractors/viewmodel-hybrid-extractor.js.map +1 -0
- package/dist/wpf/extractors/xaml-hybrid-extractor.d.ts +98 -0
- package/dist/wpf/extractors/xaml-hybrid-extractor.d.ts.map +1 -0
- package/dist/wpf/extractors/xaml-hybrid-extractor.js +444 -0
- package/dist/wpf/extractors/xaml-hybrid-extractor.js.map +1 -0
- package/dist/wpf/index.d.ts +25 -0
- package/dist/wpf/index.d.ts.map +1 -0
- package/dist/wpf/index.js +31 -0
- package/dist/wpf/index.js.map +1 -0
- package/dist/wpf/integration/wpf-callgraph-adapter.d.ts +82 -0
- package/dist/wpf/integration/wpf-callgraph-adapter.d.ts.map +1 -0
- package/dist/wpf/integration/wpf-callgraph-adapter.js +311 -0
- package/dist/wpf/integration/wpf-callgraph-adapter.js.map +1 -0
- package/dist/wpf/integration/wpf-data-flow-tracer.d.ts +129 -0
- package/dist/wpf/integration/wpf-data-flow-tracer.d.ts.map +1 -0
- package/dist/wpf/integration/wpf-data-flow-tracer.js +367 -0
- package/dist/wpf/integration/wpf-data-flow-tracer.js.map +1 -0
- package/dist/wpf/linkers/datacontext-resolver.d.ts +66 -0
- package/dist/wpf/linkers/datacontext-resolver.d.ts.map +1 -0
- package/dist/wpf/linkers/datacontext-resolver.js +240 -0
- package/dist/wpf/linkers/datacontext-resolver.js.map +1 -0
- package/dist/wpf/linkers/viewmodel-linker.d.ts +71 -0
- package/dist/wpf/linkers/viewmodel-linker.d.ts.map +1 -0
- package/dist/wpf/linkers/viewmodel-linker.js +268 -0
- package/dist/wpf/linkers/viewmodel-linker.js.map +1 -0
- package/dist/wpf/types.d.ts +451 -0
- package/dist/wpf/types.d.ts.map +1 -0
- package/dist/wpf/types.js +8 -0
- package/dist/wpf/types.js.map +1 -0
- package/dist/wpf/wpf-analyzer.d.ts +114 -0
- package/dist/wpf/wpf-analyzer.d.ts.map +1 -0
- package/dist/wpf/wpf-analyzer.js +332 -0
- package/dist/wpf/wpf-analyzer.js.map +1 -0
- package/dist/wrappers/integration/adapter.d.ts.map +1 -1
- package/dist/wrappers/integration/adapter.js +1 -0
- package/dist/wrappers/integration/adapter.js.map +1 -1
- package/package.json +29 -18
- package/LICENSE +0 -21
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision Mining Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator for mining architectural decisions from git history.
|
|
5
|
+
* Coordinates git walking, semantic extraction, clustering, and synthesis.
|
|
6
|
+
*/
|
|
7
|
+
import { GitWalker, createGitWalker, } from '../git/index.js';
|
|
8
|
+
import { createAllCommitExtractors, } from '../extractors/index.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Analyzer Class
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Decision Mining Analyzer
|
|
14
|
+
*/
|
|
15
|
+
export class DecisionMiningAnalyzer {
|
|
16
|
+
options;
|
|
17
|
+
gitWalker;
|
|
18
|
+
extractors;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.options = {
|
|
21
|
+
maxCommits: 1000,
|
|
22
|
+
minClusterSize: 2,
|
|
23
|
+
minConfidence: 0.5,
|
|
24
|
+
includeMergeCommits: false,
|
|
25
|
+
verbose: false,
|
|
26
|
+
...options,
|
|
27
|
+
};
|
|
28
|
+
// Build git walker options, only including defined values
|
|
29
|
+
const walkerOpts = {
|
|
30
|
+
rootDir: options.rootDir,
|
|
31
|
+
};
|
|
32
|
+
if (options.since !== undefined)
|
|
33
|
+
walkerOpts.since = options.since;
|
|
34
|
+
if (options.until !== undefined)
|
|
35
|
+
walkerOpts.until = options.until;
|
|
36
|
+
if (options.maxCommits !== undefined)
|
|
37
|
+
walkerOpts.maxCommits = options.maxCommits;
|
|
38
|
+
if (options.includeMergeCommits !== undefined)
|
|
39
|
+
walkerOpts.includeMergeCommits = options.includeMergeCommits;
|
|
40
|
+
if (options.excludePaths !== undefined)
|
|
41
|
+
walkerOpts.excludePaths = options.excludePaths;
|
|
42
|
+
this.gitWalker = createGitWalker(walkerOpts);
|
|
43
|
+
// Build extractor options, only including defined values
|
|
44
|
+
const extractorOptions = {
|
|
45
|
+
rootDir: options.rootDir,
|
|
46
|
+
includeFunctions: true,
|
|
47
|
+
};
|
|
48
|
+
if (options.usePatternData !== undefined)
|
|
49
|
+
extractorOptions.includePatterns = options.usePatternData;
|
|
50
|
+
if (options.verbose !== undefined)
|
|
51
|
+
extractorOptions.verbose = options.verbose;
|
|
52
|
+
this.extractors = createAllCommitExtractors(extractorOptions);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Run the full decision mining pipeline
|
|
56
|
+
*/
|
|
57
|
+
async mine() {
|
|
58
|
+
const startTime = Date.now();
|
|
59
|
+
const errors = [];
|
|
60
|
+
const warnings = [];
|
|
61
|
+
// Step 1: Walk git history
|
|
62
|
+
if (this.options.verbose) {
|
|
63
|
+
console.log('Step 1: Walking git history...');
|
|
64
|
+
}
|
|
65
|
+
let walkResult;
|
|
66
|
+
try {
|
|
67
|
+
walkResult = await this.gitWalker.walk();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const miningError = {
|
|
71
|
+
type: 'git-error',
|
|
72
|
+
message: `Failed to walk git history: ${error}`,
|
|
73
|
+
};
|
|
74
|
+
if (error instanceof Error && error.stack) {
|
|
75
|
+
miningError.stack = error.stack;
|
|
76
|
+
}
|
|
77
|
+
return this.createErrorResult([miningError]);
|
|
78
|
+
}
|
|
79
|
+
if (walkResult.commits.length === 0) {
|
|
80
|
+
warnings.push('No commits found in the specified range');
|
|
81
|
+
return this.createEmptyResult(warnings);
|
|
82
|
+
}
|
|
83
|
+
if (this.options.verbose) {
|
|
84
|
+
console.log(` Found ${walkResult.commits.length} commits`);
|
|
85
|
+
}
|
|
86
|
+
// Step 2: Extract semantic information from each commit
|
|
87
|
+
if (this.options.verbose) {
|
|
88
|
+
console.log('Step 2: Extracting semantic information...');
|
|
89
|
+
}
|
|
90
|
+
const extractions = [];
|
|
91
|
+
for (const commit of walkResult.commits) {
|
|
92
|
+
try {
|
|
93
|
+
const extraction = await this.extractCommit(commit);
|
|
94
|
+
extractions.push(extraction);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
errors.push({
|
|
98
|
+
type: 'extraction-error',
|
|
99
|
+
message: `Failed to extract commit ${commit.shortSha}: ${error}`,
|
|
100
|
+
commitSha: commit.sha,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Filter to significant commits
|
|
105
|
+
const significantExtractions = extractions.filter(e => e.significance >= (this.options.minConfidence || 0.5));
|
|
106
|
+
if (this.options.verbose) {
|
|
107
|
+
console.log(` ${significantExtractions.length} significant commits`);
|
|
108
|
+
}
|
|
109
|
+
// Step 3: Cluster related commits
|
|
110
|
+
if (this.options.verbose) {
|
|
111
|
+
console.log('Step 3: Clustering commits...');
|
|
112
|
+
}
|
|
113
|
+
const { clusters, rejected } = this.clusterCommits(significantExtractions);
|
|
114
|
+
if (this.options.verbose) {
|
|
115
|
+
console.log(` ${clusters.length} clusters formed`);
|
|
116
|
+
}
|
|
117
|
+
// Step 4: Synthesize decisions from clusters
|
|
118
|
+
if (this.options.verbose) {
|
|
119
|
+
console.log('Step 4: Synthesizing decisions...');
|
|
120
|
+
}
|
|
121
|
+
const decisions = [];
|
|
122
|
+
for (const cluster of clusters) {
|
|
123
|
+
try {
|
|
124
|
+
const decision = this.synthesizeDecision(cluster, extractions);
|
|
125
|
+
if (decision.confidenceScore >= (this.options.minConfidence || 0.5)) {
|
|
126
|
+
decisions.push(decision);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
errors.push({
|
|
131
|
+
type: 'synthesis-error',
|
|
132
|
+
message: `Failed to synthesize decision from cluster: ${error}`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Step 5: Build summary
|
|
137
|
+
const summary = this.buildSummary(decisions, walkResult, extractions, Date.now() - startTime);
|
|
138
|
+
return {
|
|
139
|
+
decisions,
|
|
140
|
+
summary,
|
|
141
|
+
rejectedClusters: rejected,
|
|
142
|
+
errors,
|
|
143
|
+
warnings,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Extract semantic information from a single commit
|
|
148
|
+
*/
|
|
149
|
+
async extractCommit(commit) {
|
|
150
|
+
// Determine primary language
|
|
151
|
+
const languageCounts = new Map();
|
|
152
|
+
for (const file of commit.files) {
|
|
153
|
+
if (file.language !== 'other' && file.language !== 'config' && file.language !== 'docs') {
|
|
154
|
+
const lang = file.language;
|
|
155
|
+
languageCounts.set(lang, (languageCounts.get(lang) || 0) + 1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Find primary language
|
|
159
|
+
let primaryLanguage = 'other';
|
|
160
|
+
let maxCount = 0;
|
|
161
|
+
for (const [lang, count] of languageCounts) {
|
|
162
|
+
if (count > maxCount) {
|
|
163
|
+
maxCount = count;
|
|
164
|
+
primaryLanguage = lang;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (languageCounts.size > 1 && maxCount < commit.files.length * 0.7) {
|
|
168
|
+
primaryLanguage = 'mixed';
|
|
169
|
+
}
|
|
170
|
+
// Use appropriate extractor
|
|
171
|
+
if (primaryLanguage !== 'mixed' && primaryLanguage !== 'other') {
|
|
172
|
+
const extractor = this.extractors.get(primaryLanguage);
|
|
173
|
+
if (extractor) {
|
|
174
|
+
return extractor.extract(commit);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// For mixed or other, use TypeScript extractor as fallback
|
|
178
|
+
const tsExtractor = this.extractors.get('typescript');
|
|
179
|
+
return tsExtractor.extract(commit);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Cluster related commits together
|
|
183
|
+
*/
|
|
184
|
+
clusterCommits(extractions) {
|
|
185
|
+
const clusters = [];
|
|
186
|
+
const rejected = [];
|
|
187
|
+
const used = new Set();
|
|
188
|
+
// Sort by date
|
|
189
|
+
const sorted = [...extractions].sort((a, b) => a.commit.date.getTime() - b.commit.date.getTime());
|
|
190
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
191
|
+
const current = sorted[i];
|
|
192
|
+
if (!current || used.has(current.commit.sha))
|
|
193
|
+
continue;
|
|
194
|
+
const cluster = this.buildCluster(sorted, i, used);
|
|
195
|
+
if (cluster.commits.length >= (this.options.minClusterSize || 2)) {
|
|
196
|
+
clusters.push(cluster);
|
|
197
|
+
}
|
|
198
|
+
else if (cluster.commits.length > 0) {
|
|
199
|
+
rejected.push(cluster);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return { clusters, rejected };
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Build a cluster starting from a seed commit
|
|
206
|
+
*/
|
|
207
|
+
buildCluster(extractions, seedIndex, used) {
|
|
208
|
+
const seed = extractions[seedIndex];
|
|
209
|
+
if (!seed) {
|
|
210
|
+
// Return empty cluster if seed is undefined
|
|
211
|
+
return this.createEmptyCluster();
|
|
212
|
+
}
|
|
213
|
+
const clusterExtractions = [seed];
|
|
214
|
+
used.add(seed.commit.sha);
|
|
215
|
+
// Look for related commits within temporal window
|
|
216
|
+
const temporalThreshold = 14 * 24 * 60 * 60 * 1000; // 14 days
|
|
217
|
+
for (let j = seedIndex + 1; j < extractions.length; j++) {
|
|
218
|
+
const candidate = extractions[j];
|
|
219
|
+
if (!candidate || used.has(candidate.commit.sha))
|
|
220
|
+
continue;
|
|
221
|
+
// Check temporal proximity
|
|
222
|
+
const timeDiff = candidate.commit.date.getTime() - seed.commit.date.getTime();
|
|
223
|
+
if (timeDiff > temporalThreshold)
|
|
224
|
+
break;
|
|
225
|
+
// Check similarity
|
|
226
|
+
const similarity = this.calculateSimilarity(seed, candidate);
|
|
227
|
+
if (similarity >= 0.3) {
|
|
228
|
+
clusterExtractions.push(candidate);
|
|
229
|
+
used.add(candidate.commit.sha);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return this.createCluster(clusterExtractions);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Create an empty cluster (for edge cases)
|
|
236
|
+
*/
|
|
237
|
+
createEmptyCluster() {
|
|
238
|
+
return {
|
|
239
|
+
id: 'empty-cluster',
|
|
240
|
+
commits: [],
|
|
241
|
+
commitShas: new Set(),
|
|
242
|
+
clusterReasons: [],
|
|
243
|
+
similarity: 0,
|
|
244
|
+
dateRange: { start: new Date(), end: new Date() },
|
|
245
|
+
duration: '0 days',
|
|
246
|
+
filesAffected: [],
|
|
247
|
+
languages: [],
|
|
248
|
+
primaryLanguage: 'mixed',
|
|
249
|
+
totalLinesChanged: 0,
|
|
250
|
+
authors: [],
|
|
251
|
+
patternsAffected: [],
|
|
252
|
+
dependencyChanges: [],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Calculate similarity between two extractions
|
|
257
|
+
*/
|
|
258
|
+
calculateSimilarity(a, b) {
|
|
259
|
+
let score = 0;
|
|
260
|
+
let weights = 0;
|
|
261
|
+
// File overlap
|
|
262
|
+
const aFiles = new Set(a.commit.files.map(f => f.path));
|
|
263
|
+
const bFiles = new Set(b.commit.files.map(f => f.path));
|
|
264
|
+
const overlap = [...aFiles].filter(f => bFiles.has(f)).length;
|
|
265
|
+
const fileOverlap = overlap / Math.max(aFiles.size, bFiles.size);
|
|
266
|
+
score += fileOverlap * 0.4;
|
|
267
|
+
weights += 0.4;
|
|
268
|
+
// Pattern similarity
|
|
269
|
+
const aPatterns = new Set(a.patternsAffected.map(p => p.patternId));
|
|
270
|
+
const bPatterns = new Set(b.patternsAffected.map(p => p.patternId));
|
|
271
|
+
if (aPatterns.size > 0 && bPatterns.size > 0) {
|
|
272
|
+
const patternOverlap = [...aPatterns].filter(p => bPatterns.has(p)).length;
|
|
273
|
+
const patternSim = patternOverlap / Math.max(aPatterns.size, bPatterns.size);
|
|
274
|
+
score += patternSim * 0.3;
|
|
275
|
+
weights += 0.3;
|
|
276
|
+
}
|
|
277
|
+
// Message keyword similarity
|
|
278
|
+
const aKeywords = new Set(a.messageSignals.filter(s => s.type === 'keyword').map(s => s.value));
|
|
279
|
+
const bKeywords = new Set(b.messageSignals.filter(s => s.type === 'keyword').map(s => s.value));
|
|
280
|
+
if (aKeywords.size > 0 && bKeywords.size > 0) {
|
|
281
|
+
const keywordOverlap = [...aKeywords].filter(k => bKeywords.has(k)).length;
|
|
282
|
+
const keywordSim = keywordOverlap / Math.max(aKeywords.size, bKeywords.size);
|
|
283
|
+
score += keywordSim * 0.2;
|
|
284
|
+
weights += 0.2;
|
|
285
|
+
}
|
|
286
|
+
// Author similarity
|
|
287
|
+
if (a.commit.authorEmail === b.commit.authorEmail) {
|
|
288
|
+
score += 0.1;
|
|
289
|
+
}
|
|
290
|
+
weights += 0.1;
|
|
291
|
+
return weights > 0 ? score / weights : 0;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Create a cluster from extractions
|
|
295
|
+
*/
|
|
296
|
+
createCluster(extractions) {
|
|
297
|
+
const commits = extractions.map(e => e.commit);
|
|
298
|
+
const dates = commits.map(c => c.date.getTime());
|
|
299
|
+
const start = new Date(Math.min(...dates));
|
|
300
|
+
const end = new Date(Math.max(...dates));
|
|
301
|
+
const durationMs = end.getTime() - start.getTime();
|
|
302
|
+
// Aggregate files
|
|
303
|
+
const filesSet = new Set();
|
|
304
|
+
for (const e of extractions) {
|
|
305
|
+
for (const f of e.commit.files) {
|
|
306
|
+
filesSet.add(f.path);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Aggregate languages
|
|
310
|
+
const languagesSet = new Set();
|
|
311
|
+
for (const e of extractions) {
|
|
312
|
+
for (const lang of e.languagesAffected) {
|
|
313
|
+
languagesSet.add(lang);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Aggregate patterns
|
|
317
|
+
const patternsMap = new Map();
|
|
318
|
+
for (const e of extractions) {
|
|
319
|
+
for (const p of e.patternsAffected) {
|
|
320
|
+
if (!patternsMap.has(p.patternId)) {
|
|
321
|
+
patternsMap.set(p.patternId, p);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Aggregate dependencies
|
|
326
|
+
const depsMap = new Map();
|
|
327
|
+
for (const e of extractions) {
|
|
328
|
+
for (const d of e.dependencyChanges) {
|
|
329
|
+
if (!depsMap.has(d.name)) {
|
|
330
|
+
depsMap.set(d.name, d);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Calculate total lines changed
|
|
335
|
+
const totalLines = commits.reduce((sum, c) => sum + c.files.reduce((s, f) => s + f.additions + f.deletions, 0), 0);
|
|
336
|
+
// Get unique authors
|
|
337
|
+
const authors = [...new Set(commits.map(c => c.authorName))];
|
|
338
|
+
// Determine primary language
|
|
339
|
+
const langCounts = new Map();
|
|
340
|
+
for (const lang of languagesSet) {
|
|
341
|
+
langCounts.set(lang, extractions.filter(e => e.primaryLanguage === lang).length);
|
|
342
|
+
}
|
|
343
|
+
let primaryLang = 'mixed';
|
|
344
|
+
let maxLangCount = 0;
|
|
345
|
+
for (const [lang, count] of langCounts) {
|
|
346
|
+
if (count > maxLangCount) {
|
|
347
|
+
maxLangCount = count;
|
|
348
|
+
primaryLang = lang;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Build cluster reasons
|
|
352
|
+
const reasons = [];
|
|
353
|
+
// Temporal reason
|
|
354
|
+
const daySpan = Math.ceil(durationMs / (24 * 60 * 60 * 1000));
|
|
355
|
+
reasons.push({
|
|
356
|
+
type: 'temporal',
|
|
357
|
+
description: `Commits span ${daySpan} days`,
|
|
358
|
+
daysSpan: daySpan,
|
|
359
|
+
});
|
|
360
|
+
// File overlap reason
|
|
361
|
+
if (filesSet.size < commits.length * 3) {
|
|
362
|
+
reasons.push({
|
|
363
|
+
type: 'file-overlap',
|
|
364
|
+
files: [...filesSet].slice(0, 5),
|
|
365
|
+
overlapPercent: filesSet.size / (commits.length * 3),
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
id: `cluster-${commits[0]?.shortSha ?? 'unknown'}-${commits.length}`,
|
|
370
|
+
commits,
|
|
371
|
+
commitShas: new Set(commits.map(c => c.sha)),
|
|
372
|
+
clusterReasons: reasons,
|
|
373
|
+
similarity: 0.5, // Placeholder
|
|
374
|
+
dateRange: { start, end },
|
|
375
|
+
duration: this.formatDuration(durationMs),
|
|
376
|
+
filesAffected: [...filesSet],
|
|
377
|
+
languages: [...languagesSet],
|
|
378
|
+
primaryLanguage: primaryLang,
|
|
379
|
+
totalLinesChanged: totalLines,
|
|
380
|
+
authors,
|
|
381
|
+
patternsAffected: [...patternsMap.values()],
|
|
382
|
+
dependencyChanges: [...depsMap.values()],
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Synthesize a decision from a cluster
|
|
387
|
+
*/
|
|
388
|
+
synthesizeDecision(cluster, allExtractions) {
|
|
389
|
+
// Get extractions for this cluster
|
|
390
|
+
const clusterExtractions = allExtractions.filter(e => cluster.commitShas.has(e.commit.sha));
|
|
391
|
+
// Determine category from signals
|
|
392
|
+
const category = this.inferCategory(clusterExtractions);
|
|
393
|
+
// Generate title
|
|
394
|
+
const title = this.generateTitle(cluster, clusterExtractions, category);
|
|
395
|
+
// Calculate confidence
|
|
396
|
+
const confidenceScore = this.calculateConfidence(cluster, clusterExtractions);
|
|
397
|
+
const confidence = this.scoreToLevel(confidenceScore);
|
|
398
|
+
// Generate ADR content
|
|
399
|
+
const adr = this.generateADR(cluster, clusterExtractions, category);
|
|
400
|
+
// Generate decision ID
|
|
401
|
+
const id = `DEC-${cluster.commits[0]?.shortSha?.toUpperCase() ?? 'UNKNOWN'}`;
|
|
402
|
+
return {
|
|
403
|
+
id,
|
|
404
|
+
title,
|
|
405
|
+
status: 'draft',
|
|
406
|
+
category,
|
|
407
|
+
confidence,
|
|
408
|
+
confidenceScore,
|
|
409
|
+
dateRange: cluster.dateRange,
|
|
410
|
+
duration: cluster.duration,
|
|
411
|
+
cluster,
|
|
412
|
+
patternsChanged: cluster.patternsAffected,
|
|
413
|
+
dependenciesChanged: cluster.dependencyChanges,
|
|
414
|
+
adr,
|
|
415
|
+
currentCodeLocations: [], // Would need call graph integration
|
|
416
|
+
relatedDecisions: [],
|
|
417
|
+
tags: this.generateTags(cluster, category),
|
|
418
|
+
minedAt: new Date(),
|
|
419
|
+
lastUpdated: new Date(),
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Infer decision category from extractions
|
|
424
|
+
*/
|
|
425
|
+
inferCategory(extractions) {
|
|
426
|
+
const categoryCounts = new Map();
|
|
427
|
+
for (const e of extractions) {
|
|
428
|
+
// From message signals
|
|
429
|
+
for (const signal of e.messageSignals) {
|
|
430
|
+
if (signal.categoryHint) {
|
|
431
|
+
categoryCounts.set(signal.categoryHint, (categoryCounts.get(signal.categoryHint) || 0) + signal.confidence);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// From architectural signals
|
|
435
|
+
for (const signal of e.architecturalSignals) {
|
|
436
|
+
const category = this.signalTypeToCategory(signal.type);
|
|
437
|
+
if (category) {
|
|
438
|
+
categoryCounts.set(category, (categoryCounts.get(category) || 0) + signal.confidence);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
// From dependency changes
|
|
442
|
+
if (e.dependencyChanges.length > 0) {
|
|
443
|
+
const hasAdded = e.dependencyChanges.some(d => d.changeType === 'added');
|
|
444
|
+
const hasRemoved = e.dependencyChanges.some(d => d.changeType === 'removed');
|
|
445
|
+
if (hasAdded && !hasRemoved) {
|
|
446
|
+
categoryCounts.set('technology-adoption', (categoryCounts.get('technology-adoption') || 0) + 0.5);
|
|
447
|
+
}
|
|
448
|
+
else if (hasRemoved && !hasAdded) {
|
|
449
|
+
categoryCounts.set('technology-removal', (categoryCounts.get('technology-removal') || 0) + 0.5);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Find highest scoring category
|
|
454
|
+
let maxCategory = 'other';
|
|
455
|
+
let maxScore = 0;
|
|
456
|
+
for (const [category, score] of categoryCounts) {
|
|
457
|
+
if (score > maxScore) {
|
|
458
|
+
maxScore = score;
|
|
459
|
+
maxCategory = category;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return maxCategory;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Map architectural signal type to decision category
|
|
466
|
+
*/
|
|
467
|
+
signalTypeToCategory(signalType) {
|
|
468
|
+
const mapping = {
|
|
469
|
+
'new-abstraction': 'pattern-introduction',
|
|
470
|
+
'layer-change': 'architecture-change',
|
|
471
|
+
'api-surface-change': 'api-change',
|
|
472
|
+
'data-model-change': 'architecture-change',
|
|
473
|
+
'config-change': 'infrastructure',
|
|
474
|
+
'build-change': 'infrastructure',
|
|
475
|
+
'test-strategy-change': 'testing-strategy',
|
|
476
|
+
'error-handling-change': 'pattern-introduction',
|
|
477
|
+
'auth-change': 'security-enhancement',
|
|
478
|
+
'integration-change': 'technology-adoption',
|
|
479
|
+
};
|
|
480
|
+
return mapping[signalType] || null;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Generate a title for the decision
|
|
484
|
+
*/
|
|
485
|
+
generateTitle(cluster, extractions, category) {
|
|
486
|
+
// Try to extract from commit messages
|
|
487
|
+
const keywords = new Set();
|
|
488
|
+
for (const e of extractions) {
|
|
489
|
+
for (const signal of e.messageSignals) {
|
|
490
|
+
if (signal.type === 'keyword') {
|
|
491
|
+
keywords.add(signal.value);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// Use first commit subject as base
|
|
496
|
+
const firstCommit = cluster.commits[0];
|
|
497
|
+
const firstSubject = firstCommit?.subject ?? 'Unknown change';
|
|
498
|
+
// If we have good keywords, use them
|
|
499
|
+
if (keywords.size > 0) {
|
|
500
|
+
const keywordList = [...keywords].slice(0, 3).join(', ');
|
|
501
|
+
return `${this.categoryToVerb(category)} ${keywordList}`;
|
|
502
|
+
}
|
|
503
|
+
// Fall back to first commit subject
|
|
504
|
+
if (firstSubject.length < 60) {
|
|
505
|
+
return firstSubject;
|
|
506
|
+
}
|
|
507
|
+
return `${this.categoryToVerb(category)} (${cluster.commits.length} commits)`;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Convert category to action verb
|
|
511
|
+
*/
|
|
512
|
+
categoryToVerb(category) {
|
|
513
|
+
const verbs = {
|
|
514
|
+
'technology-adoption': 'Adopt',
|
|
515
|
+
'technology-removal': 'Remove',
|
|
516
|
+
'pattern-introduction': 'Introduce',
|
|
517
|
+
'pattern-migration': 'Migrate',
|
|
518
|
+
'architecture-change': 'Restructure',
|
|
519
|
+
'api-change': 'Update API',
|
|
520
|
+
'security-enhancement': 'Enhance security',
|
|
521
|
+
'performance-optimization': 'Optimize',
|
|
522
|
+
'refactoring': 'Refactor',
|
|
523
|
+
'testing-strategy': 'Update testing',
|
|
524
|
+
'infrastructure': 'Update infrastructure',
|
|
525
|
+
'other': 'Change',
|
|
526
|
+
};
|
|
527
|
+
return verbs[category] || 'Change';
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Calculate confidence score for a decision
|
|
531
|
+
*/
|
|
532
|
+
calculateConfidence(cluster, extractions) {
|
|
533
|
+
let score = 0;
|
|
534
|
+
// Cluster size (more commits = more confidence)
|
|
535
|
+
score += Math.min(0.2, cluster.commits.length * 0.05);
|
|
536
|
+
// Average extraction significance
|
|
537
|
+
const avgSignificance = extractions.reduce((s, e) => s + e.significance, 0) / extractions.length;
|
|
538
|
+
score += avgSignificance * 0.3;
|
|
539
|
+
// Architectural signals present
|
|
540
|
+
const hasArchSignals = extractions.some(e => e.architecturalSignals.length > 0);
|
|
541
|
+
if (hasArchSignals) {
|
|
542
|
+
score += 0.2;
|
|
543
|
+
}
|
|
544
|
+
// Dependency changes present
|
|
545
|
+
const hasDeps = cluster.dependencyChanges.length > 0;
|
|
546
|
+
if (hasDeps) {
|
|
547
|
+
score += 0.15;
|
|
548
|
+
}
|
|
549
|
+
// Pattern changes present
|
|
550
|
+
const hasPatterns = cluster.patternsAffected.length > 0;
|
|
551
|
+
if (hasPatterns) {
|
|
552
|
+
score += 0.15;
|
|
553
|
+
}
|
|
554
|
+
return Math.min(1, score);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Convert numeric score to confidence level
|
|
558
|
+
*/
|
|
559
|
+
scoreToLevel(score) {
|
|
560
|
+
if (score >= 0.7)
|
|
561
|
+
return 'high';
|
|
562
|
+
if (score >= 0.4)
|
|
563
|
+
return 'medium';
|
|
564
|
+
return 'low';
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Generate ADR content
|
|
568
|
+
*/
|
|
569
|
+
generateADR(cluster, extractions, category) {
|
|
570
|
+
// Generate context
|
|
571
|
+
const context = this.generateContext(cluster, extractions, category);
|
|
572
|
+
// Generate decision statement
|
|
573
|
+
const decision = this.generateDecisionStatement(cluster, extractions, category);
|
|
574
|
+
// Generate consequences
|
|
575
|
+
const consequences = this.generateConsequences(cluster, extractions);
|
|
576
|
+
// Build references
|
|
577
|
+
const references = cluster.commits.map(c => ({
|
|
578
|
+
type: 'commit',
|
|
579
|
+
id: c.sha,
|
|
580
|
+
title: c.subject,
|
|
581
|
+
}));
|
|
582
|
+
// Build evidence
|
|
583
|
+
const evidence = this.buildEvidence(cluster, extractions);
|
|
584
|
+
return {
|
|
585
|
+
context,
|
|
586
|
+
decision,
|
|
587
|
+
consequences,
|
|
588
|
+
references,
|
|
589
|
+
evidence,
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Generate context section
|
|
594
|
+
*/
|
|
595
|
+
generateContext(cluster, _extractions, category) {
|
|
596
|
+
const parts = [];
|
|
597
|
+
// Time context
|
|
598
|
+
parts.push(`Between ${cluster.dateRange.start.toLocaleDateString()} and ${cluster.dateRange.end.toLocaleDateString()}, ` +
|
|
599
|
+
`${cluster.commits.length} commits were made affecting ${cluster.filesAffected.length} files.`);
|
|
600
|
+
// Category-specific context
|
|
601
|
+
switch (category) {
|
|
602
|
+
case 'technology-adoption':
|
|
603
|
+
if (cluster.dependencyChanges.length > 0) {
|
|
604
|
+
const added = cluster.dependencyChanges.filter(d => d.changeType === 'added');
|
|
605
|
+
if (added.length > 0) {
|
|
606
|
+
parts.push(`New dependencies were introduced: ${added.map(d => d.name).join(', ')}.`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
break;
|
|
610
|
+
case 'technology-removal':
|
|
611
|
+
if (cluster.dependencyChanges.length > 0) {
|
|
612
|
+
const removed = cluster.dependencyChanges.filter(d => d.changeType === 'removed');
|
|
613
|
+
if (removed.length > 0) {
|
|
614
|
+
parts.push(`Dependencies were removed: ${removed.map(d => d.name).join(', ')}.`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
break;
|
|
618
|
+
case 'architecture-change':
|
|
619
|
+
parts.push(`Architectural changes were made across ${cluster.languages.join(', ')} code.`);
|
|
620
|
+
break;
|
|
621
|
+
case 'api-change':
|
|
622
|
+
parts.push('API surface changes were detected in the codebase.');
|
|
623
|
+
break;
|
|
624
|
+
default:
|
|
625
|
+
parts.push(`Changes were made primarily in ${cluster.primaryLanguage} code.`);
|
|
626
|
+
}
|
|
627
|
+
return parts.join(' ');
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Generate decision statement
|
|
631
|
+
*/
|
|
632
|
+
generateDecisionStatement(cluster, _extractions, category) {
|
|
633
|
+
// Use first commit message as base
|
|
634
|
+
const firstCommit = cluster.commits[0];
|
|
635
|
+
// Try to extract meaningful decision from commit messages
|
|
636
|
+
const subjects = cluster.commits.map(c => c.subject);
|
|
637
|
+
// Find common theme
|
|
638
|
+
if (subjects.length === 1) {
|
|
639
|
+
return subjects[0] ?? 'Unknown change';
|
|
640
|
+
}
|
|
641
|
+
// Summarize based on category
|
|
642
|
+
switch (category) {
|
|
643
|
+
case 'technology-adoption':
|
|
644
|
+
return `Adopt new technology/library as indicated by dependency additions and code changes.`;
|
|
645
|
+
case 'technology-removal':
|
|
646
|
+
return `Remove deprecated technology/library and migrate to alternatives.`;
|
|
647
|
+
case 'pattern-introduction':
|
|
648
|
+
return `Introduce new coding pattern or abstraction across the codebase.`;
|
|
649
|
+
case 'architecture-change':
|
|
650
|
+
return `Restructure code architecture affecting ${cluster.filesAffected.length} files.`;
|
|
651
|
+
case 'api-change':
|
|
652
|
+
return `Modify API surface with changes to endpoints or contracts.`;
|
|
653
|
+
case 'security-enhancement':
|
|
654
|
+
return `Enhance security measures in authentication or authorization.`;
|
|
655
|
+
case 'refactoring':
|
|
656
|
+
return `Refactor code for improved maintainability without changing behavior.`;
|
|
657
|
+
default:
|
|
658
|
+
return firstCommit?.subject ?? 'Unknown change';
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Generate consequences
|
|
663
|
+
*/
|
|
664
|
+
generateConsequences(cluster, _extractions) {
|
|
665
|
+
const consequences = [];
|
|
666
|
+
// Files affected
|
|
667
|
+
consequences.push(`${cluster.filesAffected.length} files were modified.`);
|
|
668
|
+
// Lines changed
|
|
669
|
+
consequences.push(`${cluster.totalLinesChanged} lines of code were changed.`);
|
|
670
|
+
// Dependency impact
|
|
671
|
+
if (cluster.dependencyChanges.length > 0) {
|
|
672
|
+
consequences.push(`${cluster.dependencyChanges.length} dependency changes were made.`);
|
|
673
|
+
}
|
|
674
|
+
// Pattern impact
|
|
675
|
+
if (cluster.patternsAffected.length > 0) {
|
|
676
|
+
consequences.push(`${cluster.patternsAffected.length} code patterns were affected.`);
|
|
677
|
+
}
|
|
678
|
+
return consequences;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Build evidence for the ADR
|
|
682
|
+
*/
|
|
683
|
+
buildEvidence(cluster, _extractions) {
|
|
684
|
+
const evidence = [];
|
|
685
|
+
// Commit message evidence
|
|
686
|
+
for (const commit of cluster.commits.slice(0, 3)) {
|
|
687
|
+
evidence.push({
|
|
688
|
+
type: 'commit-message',
|
|
689
|
+
description: commit.subject,
|
|
690
|
+
source: commit.sha,
|
|
691
|
+
confidence: 0.7,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
// Dependency change evidence
|
|
695
|
+
for (const dep of cluster.dependencyChanges.slice(0, 3)) {
|
|
696
|
+
evidence.push({
|
|
697
|
+
type: 'dependency-change',
|
|
698
|
+
description: `${dep.changeType}: ${dep.name}`,
|
|
699
|
+
source: dep.sourceFile,
|
|
700
|
+
confidence: 0.8,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
// Pattern change evidence
|
|
704
|
+
for (const pattern of cluster.patternsAffected.slice(0, 3)) {
|
|
705
|
+
evidence.push({
|
|
706
|
+
type: 'pattern-change',
|
|
707
|
+
description: `${pattern.changeType}: ${pattern.patternName}`,
|
|
708
|
+
source: pattern.filesAffected[0] ?? 'unknown',
|
|
709
|
+
confidence: 0.6,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
return evidence;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Generate tags for the decision
|
|
716
|
+
*/
|
|
717
|
+
generateTags(cluster, category) {
|
|
718
|
+
const tags = [category];
|
|
719
|
+
// Add language tags
|
|
720
|
+
for (const lang of cluster.languages) {
|
|
721
|
+
tags.push(lang);
|
|
722
|
+
}
|
|
723
|
+
// Add author tags if single author
|
|
724
|
+
if (cluster.authors.length === 1) {
|
|
725
|
+
tags.push(`author:${cluster.authors[0]}`);
|
|
726
|
+
}
|
|
727
|
+
return tags;
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Build summary statistics
|
|
731
|
+
*/
|
|
732
|
+
buildSummary(decisions, walkResult, extractions, duration) {
|
|
733
|
+
const byStatus = {
|
|
734
|
+
draft: 0,
|
|
735
|
+
confirmed: 0,
|
|
736
|
+
superseded: 0,
|
|
737
|
+
rejected: 0,
|
|
738
|
+
};
|
|
739
|
+
const byCategory = {
|
|
740
|
+
'technology-adoption': 0,
|
|
741
|
+
'technology-removal': 0,
|
|
742
|
+
'pattern-introduction': 0,
|
|
743
|
+
'pattern-migration': 0,
|
|
744
|
+
'architecture-change': 0,
|
|
745
|
+
'api-change': 0,
|
|
746
|
+
'security-enhancement': 0,
|
|
747
|
+
'performance-optimization': 0,
|
|
748
|
+
'refactoring': 0,
|
|
749
|
+
'testing-strategy': 0,
|
|
750
|
+
'infrastructure': 0,
|
|
751
|
+
'other': 0,
|
|
752
|
+
};
|
|
753
|
+
const byConfidence = {
|
|
754
|
+
high: 0,
|
|
755
|
+
medium: 0,
|
|
756
|
+
low: 0,
|
|
757
|
+
};
|
|
758
|
+
const byLanguage = {
|
|
759
|
+
typescript: 0,
|
|
760
|
+
javascript: 0,
|
|
761
|
+
python: 0,
|
|
762
|
+
java: 0,
|
|
763
|
+
csharp: 0,
|
|
764
|
+
php: 0,
|
|
765
|
+
mixed: 0,
|
|
766
|
+
};
|
|
767
|
+
// Count decisions
|
|
768
|
+
for (const decision of decisions) {
|
|
769
|
+
byStatus[decision.status]++;
|
|
770
|
+
byCategory[decision.category]++;
|
|
771
|
+
byConfidence[decision.confidence]++;
|
|
772
|
+
byLanguage[decision.cluster.primaryLanguage]++;
|
|
773
|
+
}
|
|
774
|
+
// Calculate top patterns
|
|
775
|
+
const patternCounts = new Map();
|
|
776
|
+
for (const decision of decisions) {
|
|
777
|
+
for (const pattern of decision.patternsChanged) {
|
|
778
|
+
patternCounts.set(pattern.patternName, (patternCounts.get(pattern.patternName) || 0) + 1);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const topPatterns = [...patternCounts.entries()]
|
|
782
|
+
.sort((a, b) => b[1] - a[1])
|
|
783
|
+
.slice(0, 10)
|
|
784
|
+
.map(([pattern, count]) => ({ pattern, count }));
|
|
785
|
+
// Calculate top dependencies
|
|
786
|
+
const depCounts = new Map();
|
|
787
|
+
for (const decision of decisions) {
|
|
788
|
+
for (const dep of decision.dependenciesChanged) {
|
|
789
|
+
depCounts.set(dep.name, (depCounts.get(dep.name) || 0) + 1);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
const topDependencies = [...depCounts.entries()]
|
|
793
|
+
.sort((a, b) => b[1] - a[1])
|
|
794
|
+
.slice(0, 10)
|
|
795
|
+
.map(([dependency, count]) => ({ dependency, count }));
|
|
796
|
+
// Calculate average cluster size
|
|
797
|
+
const avgClusterSize = decisions.length > 0
|
|
798
|
+
? decisions.reduce((sum, d) => sum + d.cluster.commits.length, 0) / decisions.length
|
|
799
|
+
: 0;
|
|
800
|
+
// Count significant commits
|
|
801
|
+
const significantCommits = extractions.filter(e => e.significance >= (this.options.minConfidence || 0.5)).length;
|
|
802
|
+
return {
|
|
803
|
+
totalDecisions: decisions.length,
|
|
804
|
+
byStatus,
|
|
805
|
+
byCategory,
|
|
806
|
+
byConfidence,
|
|
807
|
+
byLanguage,
|
|
808
|
+
dateRange: walkResult.dateRange,
|
|
809
|
+
totalCommitsAnalyzed: walkResult.commits.length,
|
|
810
|
+
significantCommits,
|
|
811
|
+
avgClusterSize,
|
|
812
|
+
topPatterns,
|
|
813
|
+
topDependencies,
|
|
814
|
+
miningDuration: duration,
|
|
815
|
+
lastMined: new Date(),
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Format duration in human-readable format
|
|
820
|
+
*/
|
|
821
|
+
formatDuration(ms) {
|
|
822
|
+
const days = Math.floor(ms / (24 * 60 * 60 * 1000));
|
|
823
|
+
const hours = Math.floor((ms % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
|
|
824
|
+
if (days > 0) {
|
|
825
|
+
return `${days} day${days > 1 ? 's' : ''}`;
|
|
826
|
+
}
|
|
827
|
+
if (hours > 0) {
|
|
828
|
+
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
|
829
|
+
}
|
|
830
|
+
return 'less than an hour';
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Create an error result
|
|
834
|
+
*/
|
|
835
|
+
createErrorResult(errors) {
|
|
836
|
+
return {
|
|
837
|
+
decisions: [],
|
|
838
|
+
summary: this.createEmptySummary(),
|
|
839
|
+
rejectedClusters: [],
|
|
840
|
+
errors,
|
|
841
|
+
warnings: [],
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Create an empty result
|
|
846
|
+
*/
|
|
847
|
+
createEmptyResult(warnings) {
|
|
848
|
+
return {
|
|
849
|
+
decisions: [],
|
|
850
|
+
summary: this.createEmptySummary(),
|
|
851
|
+
rejectedClusters: [],
|
|
852
|
+
errors: [],
|
|
853
|
+
warnings,
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Create an empty summary
|
|
858
|
+
*/
|
|
859
|
+
createEmptySummary() {
|
|
860
|
+
return {
|
|
861
|
+
totalDecisions: 0,
|
|
862
|
+
byStatus: { draft: 0, confirmed: 0, superseded: 0, rejected: 0 },
|
|
863
|
+
byCategory: {
|
|
864
|
+
'technology-adoption': 0,
|
|
865
|
+
'technology-removal': 0,
|
|
866
|
+
'pattern-introduction': 0,
|
|
867
|
+
'pattern-migration': 0,
|
|
868
|
+
'architecture-change': 0,
|
|
869
|
+
'api-change': 0,
|
|
870
|
+
'security-enhancement': 0,
|
|
871
|
+
'performance-optimization': 0,
|
|
872
|
+
'refactoring': 0,
|
|
873
|
+
'testing-strategy': 0,
|
|
874
|
+
'infrastructure': 0,
|
|
875
|
+
'other': 0,
|
|
876
|
+
},
|
|
877
|
+
byConfidence: { high: 0, medium: 0, low: 0 },
|
|
878
|
+
byLanguage: {
|
|
879
|
+
typescript: 0,
|
|
880
|
+
javascript: 0,
|
|
881
|
+
python: 0,
|
|
882
|
+
java: 0,
|
|
883
|
+
csharp: 0,
|
|
884
|
+
php: 0,
|
|
885
|
+
mixed: 0,
|
|
886
|
+
},
|
|
887
|
+
dateRange: { earliest: new Date(), latest: new Date() },
|
|
888
|
+
totalCommitsAnalyzed: 0,
|
|
889
|
+
significantCommits: 0,
|
|
890
|
+
avgClusterSize: 0,
|
|
891
|
+
topPatterns: [],
|
|
892
|
+
topDependencies: [],
|
|
893
|
+
miningDuration: 0,
|
|
894
|
+
lastMined: new Date(),
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Create a decision mining analyzer
|
|
900
|
+
*/
|
|
901
|
+
export function createDecisionMiningAnalyzer(options) {
|
|
902
|
+
return new DecisionMiningAnalyzer(options);
|
|
903
|
+
}
|
|
904
|
+
//# sourceMappingURL=decision-mining-analyzer.js.map
|