@defai.digital/ax-cli 3.4.6 → 3.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +2 -6
  2. package/README.md +109 -2
  3. package/dist/analyzers/ast/index.d.ts +9 -0
  4. package/dist/analyzers/ast/index.js +10 -0
  5. package/dist/analyzers/ast/index.js.map +1 -0
  6. package/dist/analyzers/ast/node-helpers.d.ts +81 -0
  7. package/dist/analyzers/ast/node-helpers.js +128 -0
  8. package/dist/analyzers/ast/node-helpers.js.map +1 -0
  9. package/dist/analyzers/ast/parser.d.ts +59 -0
  10. package/dist/analyzers/ast/parser.js +293 -0
  11. package/dist/analyzers/ast/parser.js.map +1 -0
  12. package/dist/analyzers/ast/traverser.d.ts +67 -0
  13. package/dist/analyzers/ast/traverser.js +156 -0
  14. package/dist/analyzers/ast/traverser.js.map +1 -0
  15. package/dist/analyzers/ast/types.d.ts +107 -0
  16. package/dist/analyzers/ast/types.js +7 -0
  17. package/dist/analyzers/ast/types.js.map +1 -0
  18. package/dist/analyzers/best-practices/index.d.ts +10 -0
  19. package/dist/analyzers/best-practices/index.js +11 -0
  20. package/dist/analyzers/best-practices/index.js.map +1 -0
  21. package/dist/analyzers/code-smells/base-smell-detector.d.ts +30 -0
  22. package/dist/analyzers/code-smells/base-smell-detector.js +44 -0
  23. package/dist/analyzers/code-smells/base-smell-detector.js.map +1 -0
  24. package/dist/analyzers/code-smells/code-smell-analyzer.d.ts +30 -0
  25. package/dist/analyzers/code-smells/code-smell-analyzer.js +167 -0
  26. package/dist/analyzers/code-smells/code-smell-analyzer.js.map +1 -0
  27. package/dist/analyzers/code-smells/detectors/data-clumps-detector.d.ts +11 -0
  28. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +66 -0
  29. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -0
  30. package/dist/analyzers/code-smells/detectors/dead-code-detector.d.ts +11 -0
  31. package/dist/analyzers/code-smells/detectors/dead-code-detector.js +53 -0
  32. package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -0
  33. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.d.ts +11 -0
  34. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +51 -0
  35. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -0
  36. package/dist/analyzers/code-smells/detectors/feature-envy-detector.d.ts +11 -0
  37. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +64 -0
  38. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -0
  39. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.d.ts +11 -0
  40. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +56 -0
  41. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -0
  42. package/dist/analyzers/code-smells/detectors/large-class-detector.d.ts +13 -0
  43. package/dist/analyzers/code-smells/detectors/large-class-detector.js +58 -0
  44. package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -0
  45. package/dist/analyzers/code-smells/detectors/long-method-detector.d.ts +12 -0
  46. package/dist/analyzers/code-smells/detectors/long-method-detector.js +52 -0
  47. package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -0
  48. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.d.ts +12 -0
  49. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +50 -0
  50. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -0
  51. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.d.ts +12 -0
  52. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +54 -0
  53. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -0
  54. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.d.ts +13 -0
  55. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +71 -0
  56. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -0
  57. package/dist/analyzers/code-smells/index.d.ts +16 -0
  58. package/dist/analyzers/code-smells/index.js +19 -0
  59. package/dist/analyzers/code-smells/index.js.map +1 -0
  60. package/dist/analyzers/code-smells/types.d.ts +82 -0
  61. package/dist/analyzers/code-smells/types.js +30 -0
  62. package/dist/analyzers/code-smells/types.js.map +1 -0
  63. package/dist/analyzers/dependency/circular-detector.d.ts +17 -0
  64. package/dist/analyzers/dependency/circular-detector.js +71 -0
  65. package/dist/analyzers/dependency/circular-detector.js.map +1 -0
  66. package/dist/analyzers/dependency/coupling-calculator.d.ts +24 -0
  67. package/dist/analyzers/dependency/coupling-calculator.js +86 -0
  68. package/dist/analyzers/dependency/coupling-calculator.js.map +1 -0
  69. package/dist/analyzers/dependency/dependency-analyzer.d.ts +40 -0
  70. package/dist/analyzers/dependency/dependency-analyzer.js +214 -0
  71. package/dist/analyzers/dependency/dependency-analyzer.js.map +1 -0
  72. package/dist/analyzers/dependency/dependency-graph.d.ts +57 -0
  73. package/dist/analyzers/dependency/dependency-graph.js +186 -0
  74. package/dist/analyzers/dependency/dependency-graph.js.map +1 -0
  75. package/dist/analyzers/dependency/index.d.ts +8 -0
  76. package/dist/analyzers/dependency/index.js +8 -0
  77. package/dist/analyzers/dependency/index.js.map +1 -0
  78. package/dist/analyzers/dependency/types.d.ts +105 -0
  79. package/dist/analyzers/dependency/types.js +5 -0
  80. package/dist/analyzers/dependency/types.js.map +1 -0
  81. package/dist/analyzers/git/churn-calculator.d.ts +34 -0
  82. package/dist/analyzers/git/churn-calculator.js +214 -0
  83. package/dist/analyzers/git/churn-calculator.js.map +1 -0
  84. package/dist/analyzers/git/git-analyzer.d.ts +19 -0
  85. package/dist/analyzers/git/git-analyzer.js +71 -0
  86. package/dist/analyzers/git/git-analyzer.js.map +1 -0
  87. package/dist/analyzers/git/hotspot-detector.d.ts +34 -0
  88. package/dist/analyzers/git/hotspot-detector.js +170 -0
  89. package/dist/analyzers/git/hotspot-detector.js.map +1 -0
  90. package/dist/analyzers/git/index.d.ts +7 -0
  91. package/dist/analyzers/git/index.js +7 -0
  92. package/dist/analyzers/git/index.js.map +1 -0
  93. package/dist/analyzers/git/types.d.ts +88 -0
  94. package/dist/analyzers/git/types.js +5 -0
  95. package/dist/analyzers/git/types.js.map +1 -0
  96. package/dist/analyzers/metrics/halstead-calculator.d.ts +30 -0
  97. package/dist/analyzers/metrics/halstead-calculator.js +150 -0
  98. package/dist/analyzers/metrics/halstead-calculator.js.map +1 -0
  99. package/dist/analyzers/metrics/index.d.ts +9 -0
  100. package/dist/analyzers/metrics/index.js +9 -0
  101. package/dist/analyzers/metrics/index.js.map +1 -0
  102. package/dist/analyzers/metrics/maintainability-calculator.d.ts +17 -0
  103. package/dist/analyzers/metrics/maintainability-calculator.js +46 -0
  104. package/dist/analyzers/metrics/maintainability-calculator.js.map +1 -0
  105. package/dist/analyzers/metrics/metrics-analyzer.d.ts +32 -0
  106. package/dist/analyzers/metrics/metrics-analyzer.js +140 -0
  107. package/dist/analyzers/metrics/metrics-analyzer.js.map +1 -0
  108. package/dist/analyzers/metrics/types.d.ts +67 -0
  109. package/dist/analyzers/metrics/types.js +5 -0
  110. package/dist/analyzers/metrics/types.js.map +1 -0
  111. package/dist/analyzers/security/base-detector.d.ts +58 -0
  112. package/dist/analyzers/security/base-detector.js +104 -0
  113. package/dist/analyzers/security/base-detector.js.map +1 -0
  114. package/dist/analyzers/security/detectors/command-injection-detector.d.ts +12 -0
  115. package/dist/analyzers/security/detectors/command-injection-detector.js +84 -0
  116. package/dist/analyzers/security/detectors/command-injection-detector.js.map +1 -0
  117. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.d.ts +16 -0
  118. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js +140 -0
  119. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js.map +1 -0
  120. package/dist/analyzers/security/detectors/insecure-deserialization-detector.d.ts +12 -0
  121. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js +109 -0
  122. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js.map +1 -0
  123. package/dist/analyzers/security/detectors/insecure-random-detector.d.ts +12 -0
  124. package/dist/analyzers/security/detectors/insecure-random-detector.js +61 -0
  125. package/dist/analyzers/security/detectors/insecure-random-detector.js.map +1 -0
  126. package/dist/analyzers/security/detectors/path-traversal-detector.d.ts +12 -0
  127. package/dist/analyzers/security/detectors/path-traversal-detector.js +82 -0
  128. package/dist/analyzers/security/detectors/path-traversal-detector.js.map +1 -0
  129. package/dist/analyzers/security/detectors/sql-injection-detector.d.ts +12 -0
  130. package/dist/analyzers/security/detectors/sql-injection-detector.js +88 -0
  131. package/dist/analyzers/security/detectors/sql-injection-detector.js.map +1 -0
  132. package/dist/analyzers/security/detectors/weak-crypto-detector.d.ts +12 -0
  133. package/dist/analyzers/security/detectors/weak-crypto-detector.js +104 -0
  134. package/dist/analyzers/security/detectors/weak-crypto-detector.js.map +1 -0
  135. package/dist/analyzers/security/detectors/xss-detector.d.ts +12 -0
  136. package/dist/analyzers/security/detectors/xss-detector.js +90 -0
  137. package/dist/analyzers/security/detectors/xss-detector.js.map +1 -0
  138. package/dist/analyzers/security/index.d.ts +16 -0
  139. package/dist/analyzers/security/index.js +18 -0
  140. package/dist/analyzers/security/index.js.map +1 -0
  141. package/dist/analyzers/security/security-analyzer.d.ts +38 -0
  142. package/dist/analyzers/security/security-analyzer.js +215 -0
  143. package/dist/analyzers/security/security-analyzer.js.map +1 -0
  144. package/dist/analyzers/security/types.d.ts +95 -0
  145. package/dist/analyzers/security/types.js +7 -0
  146. package/dist/analyzers/security/types.js.map +1 -0
  147. package/dist/hooks/use-enhanced-input.d.ts +0 -1
  148. package/dist/hooks/use-enhanced-input.js.map +1 -1
  149. package/dist/index.js +0 -0
  150. package/dist/mcp/validation.js +12 -6
  151. package/dist/mcp/validation.js.map +1 -1
  152. package/dist/tools/analysis-tools.d.ts +73 -0
  153. package/dist/tools/analysis-tools.js +422 -0
  154. package/dist/tools/analysis-tools.js.map +1 -0
  155. package/dist/tools/bash.js +2 -1
  156. package/dist/tools/bash.js.map +1 -1
  157. package/dist/ui/components/toast-notification.js +0 -1
  158. package/dist/ui/components/toast-notification.js.map +1 -1
  159. package/dist/ui/components/welcome-panel.js +1 -1
  160. package/dist/ui/components/welcome-panel.js.map +1 -1
  161. package/dist/ui/hooks/use-input-history.d.ts +9 -0
  162. package/dist/ui/hooks/use-input-history.js +117 -0
  163. package/dist/ui/hooks/use-input-history.js.map +1 -0
  164. package/dist/utils/parallel-analyzer.js +30 -17
  165. package/dist/utils/parallel-analyzer.js.map +1 -1
  166. package/eslint.config.js +3 -0
  167. package/package.json +5 -5
  168. package/vitest.config.ts +1 -0
  169. package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
  170. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
  171. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
  172. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
  173. package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
  174. package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
  175. package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
  176. package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
  177. package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
  178. package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
  179. package/automatosx.config.json +0 -333
  180. package/config/messages.yaml +0 -75
  181. package/config/models.yaml +0 -66
  182. package/config/prompts.yaml +0 -156
  183. package/config/settings.yaml +0 -86
  184. package/dist/commands/weather.d.ts +0 -8
  185. package/dist/commands/weather.js +0 -160
  186. package/dist/commands/weather.js.map +0 -1
  187. package/dist/grok/client.d.ts +0 -144
  188. package/dist/grok/client.js +0 -237
  189. package/dist/grok/client.js.map +0 -1
  190. package/dist/grok/tools.d.ts +0 -8
  191. package/dist/grok/tools.js +0 -318
  192. package/dist/grok/tools.js.map +0 -1
  193. package/dist/grok/types.d.ts +0 -291
  194. package/dist/grok/types.js +0 -127
  195. package/dist/grok/types.js.map +0 -1
  196. package/dist/tools/morph-editor.d.ts +0 -36
  197. package/dist/tools/morph-editor.js +0 -308
  198. package/dist/tools/morph-editor.js.map +0 -1
  199. package/dist/ui/components/session-recovery.d.ts +0 -12
  200. package/dist/ui/components/session-recovery.js +0 -93
  201. package/dist/ui/components/session-recovery.js.map +0 -1
  202. package/dist/utils/model-config.d.ts +0 -28
  203. package/dist/utils/model-config.js +0 -43
  204. package/dist/utils/model-config.js.map +0 -1
  205. package/dist/utils/tool-helpers.d.ts +0 -25
  206. package/dist/utils/tool-helpers.js +0 -79
  207. package/dist/utils/tool-helpers.js.map +0 -1
  208. package/packages/schemas/dist/index.d.ts +0 -14
  209. package/packages/schemas/dist/index.d.ts.map +0 -1
  210. package/packages/schemas/dist/index.js +0 -19
  211. package/packages/schemas/dist/index.js.map +0 -1
  212. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  213. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  214. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  215. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  216. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  217. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  218. package/packages/schemas/dist/public/core/enums.js +0 -222
  219. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  220. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  221. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  222. package/packages/schemas/dist/public/core/id-types.js +0 -136
  223. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Git Analyzer
3
+ *
4
+ * Main orchestrator for Git history analysis
5
+ */
6
+ import { ChurnCalculator } from './churn-calculator.js';
7
+ import { HotspotDetector } from './hotspot-detector.js';
8
+ export class GitAnalyzer {
9
+ churnCalculator;
10
+ hotspotDetector;
11
+ constructor(repositoryPath) {
12
+ this.churnCalculator = new ChurnCalculator(repositoryPath);
13
+ this.hotspotDetector = new HotspotDetector();
14
+ }
15
+ /**
16
+ * Perform complete Git analysis
17
+ */
18
+ async analyze(options = {}) {
19
+ const timestamp = new Date();
20
+ // Calculate churn metrics
21
+ const churnMetrics = await this.churnCalculator.calculateChurn(options);
22
+ // Calculate contributor statistics
23
+ const contributors = await this.churnCalculator.calculateContributorStats(options);
24
+ // Detect hotspots
25
+ const hotspots = await this.hotspotDetector.detectHotspots(churnMetrics, options);
26
+ // Calculate summary
27
+ const summary = this.calculateSummary(churnMetrics, hotspots, contributors);
28
+ return Object.freeze({
29
+ hotspots: Object.freeze(hotspots),
30
+ churnMetrics: Object.freeze(churnMetrics),
31
+ contributors: Object.freeze(contributors),
32
+ summary: Object.freeze(summary),
33
+ timestamp,
34
+ });
35
+ }
36
+ /**
37
+ * Calculate summary statistics
38
+ */
39
+ calculateSummary(churnMetrics, hotspots, contributors) {
40
+ const totalCommits = contributors.reduce((sum, c) => sum + c.commitCount, 0);
41
+ const averageChurn = churnMetrics.length > 0
42
+ ? churnMetrics.reduce((sum, c) => sum + c.totalChurn, 0) / churnMetrics.length
43
+ : 0;
44
+ const topContributor = contributors.length > 0
45
+ ? contributors[0].author
46
+ : 'Unknown';
47
+ // Determine date range
48
+ let earliestDate = new Date();
49
+ let latestDate = new Date(0);
50
+ for (const contributor of contributors) {
51
+ if (contributor.firstCommit < earliestDate) {
52
+ earliestDate = contributor.firstCommit;
53
+ }
54
+ if (contributor.lastCommit > latestDate) {
55
+ latestDate = contributor.lastCommit;
56
+ }
57
+ }
58
+ return {
59
+ totalCommits,
60
+ filesAnalyzed: churnMetrics.length,
61
+ hotspotCount: hotspots.length,
62
+ averageChurn: Math.round(averageChurn),
63
+ topContributor,
64
+ dateRange: {
65
+ from: earliestDate,
66
+ to: latestDate,
67
+ },
68
+ };
69
+ }
70
+ }
71
+ //# sourceMappingURL=git-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/git/git-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Hotspot Detector
3
+ *
4
+ * Identifies code hotspots using churn × complexity formula
5
+ */
6
+ import type { FileChurn, CodeHotspot, GitAnalysisOptions } from './types.js';
7
+ export declare class HotspotDetector {
8
+ private astParser;
9
+ constructor();
10
+ /**
11
+ * Detect hotspots from churn metrics
12
+ */
13
+ detectHotspots(churnMetrics: readonly FileChurn[], options?: GitAnalysisOptions): Promise<CodeHotspot[]>;
14
+ /**
15
+ * Get complexity metrics from file
16
+ */
17
+ private getComplexityMetrics;
18
+ /**
19
+ * Normalize complexity to 0-100 scale
20
+ */
21
+ private normalizeComplexity;
22
+ /**
23
+ * Calculate severity based on hotspot score
24
+ */
25
+ private calculateSeverity;
26
+ /**
27
+ * Generate reason for hotspot
28
+ */
29
+ private generateReason;
30
+ /**
31
+ * Generate recommendation
32
+ */
33
+ private generateRecommendation;
34
+ }
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Hotspot Detector
3
+ *
4
+ * Identifies code hotspots using churn × complexity formula
5
+ */
6
+ import { ASTParser } from '../ast/parser.js';
7
+ export class HotspotDetector {
8
+ astParser;
9
+ constructor() {
10
+ this.astParser = new ASTParser();
11
+ }
12
+ /**
13
+ * Detect hotspots from churn metrics
14
+ */
15
+ async detectHotspots(churnMetrics, options = {}) {
16
+ const threshold = options.hotspotThreshold ?? 70;
17
+ const hotspots = [];
18
+ // Calculate max values for normalization
19
+ const maxChurn = Math.max(...churnMetrics.map(c => c.totalChurn), 1);
20
+ const maxCommits = Math.max(...churnMetrics.map(c => c.commitCount), 1);
21
+ for (const churn of churnMetrics) {
22
+ try {
23
+ // Get complexity metrics from AST
24
+ const complexity = await this.getComplexityMetrics(churn.filePath);
25
+ if (!complexity)
26
+ continue;
27
+ // Normalize churn (0-100)
28
+ const normalizedChurn = (churn.totalChurn / maxChurn) * 100;
29
+ const normalizedCommits = (churn.commitCount / maxCommits) * 100;
30
+ const churnScore = (normalizedChurn * 0.6 + normalizedCommits * 0.4);
31
+ // Normalize complexity (0-100)
32
+ const complexityScore = this.normalizeComplexity(complexity.average, complexity.max);
33
+ // Calculate hotspot score using weighted formula
34
+ // Churn: 40%, Complexity: 30%, Commit Frequency: 30%
35
+ const hotspotScore = Math.round(churnScore * 0.4 +
36
+ complexityScore * 0.3 +
37
+ normalizedCommits * 0.3);
38
+ // Only include if above threshold
39
+ if (hotspotScore >= threshold) {
40
+ const severity = this.calculateSeverity(hotspotScore);
41
+ const reason = this.generateReason(churn, complexity, hotspotScore);
42
+ const recommendation = this.generateRecommendation(churn, complexity, severity);
43
+ hotspots.push(Object.freeze({
44
+ filePath: churn.filePath,
45
+ hotspotScore,
46
+ churnScore: Math.round(churnScore),
47
+ complexityScore: Math.round(complexityScore),
48
+ commitCount: churn.commitCount,
49
+ totalChurn: churn.totalChurn,
50
+ averageComplexity: complexity.average,
51
+ maxComplexity: complexity.max,
52
+ severity,
53
+ reason,
54
+ recommendation,
55
+ }));
56
+ }
57
+ }
58
+ catch (error) {
59
+ // Skip files that can't be analyzed
60
+ continue;
61
+ }
62
+ }
63
+ // Sort by hotspot score (descending)
64
+ return hotspots.sort((a, b) => b.hotspotScore - a.hotspotScore);
65
+ }
66
+ /**
67
+ * Get complexity metrics from file
68
+ */
69
+ async getComplexityMetrics(filePath) {
70
+ try {
71
+ const ast = this.astParser.parseFile(filePath);
72
+ const complexities = [];
73
+ // Collect function complexities
74
+ for (const func of ast.functions) {
75
+ complexities.push(func.complexity);
76
+ }
77
+ // Collect method complexities
78
+ for (const cls of ast.classes) {
79
+ for (const method of cls.methods) {
80
+ complexities.push(method.complexity);
81
+ }
82
+ }
83
+ if (complexities.length === 0) {
84
+ return null;
85
+ }
86
+ const average = complexities.reduce((sum, c) => sum + c, 0) / complexities.length;
87
+ const max = Math.max(...complexities);
88
+ return { average, max };
89
+ }
90
+ catch (error) {
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Normalize complexity to 0-100 scale
96
+ */
97
+ normalizeComplexity(average, max) {
98
+ // McCabe complexity thresholds:
99
+ // 1-10: Simple
100
+ // 11-20: Moderate
101
+ // 21-50: Complex
102
+ // 50+: Very complex
103
+ const avgScore = Math.min(100, (average / 20) * 100);
104
+ const maxScore = Math.min(100, (max / 50) * 100);
105
+ // Weight average more than max
106
+ return avgScore * 0.7 + maxScore * 0.3;
107
+ }
108
+ /**
109
+ * Calculate severity based on hotspot score
110
+ */
111
+ calculateSeverity(score) {
112
+ if (score >= 90)
113
+ return 'CRITICAL';
114
+ if (score >= 80)
115
+ return 'HIGH';
116
+ if (score >= 70)
117
+ return 'MEDIUM';
118
+ return 'LOW';
119
+ }
120
+ /**
121
+ * Generate reason for hotspot
122
+ */
123
+ generateReason(churn, complexity, score) {
124
+ const reasons = [];
125
+ if (churn.commitCount > 20) {
126
+ reasons.push(`high change frequency (${churn.commitCount} commits)`);
127
+ }
128
+ if (churn.totalChurn > 500) {
129
+ reasons.push(`high churn (${churn.totalChurn} lines changed)`);
130
+ }
131
+ if (complexity.average > 10) {
132
+ reasons.push(`high average complexity (${complexity.average.toFixed(1)})`);
133
+ }
134
+ if (complexity.max > 20) {
135
+ reasons.push(`very complex functions (max: ${complexity.max})`);
136
+ }
137
+ if (churn.authors.length > 5) {
138
+ reasons.push(`many contributors (${churn.authors.length})`);
139
+ }
140
+ return `Hotspot (score: ${score}/100): ${reasons.join(', ')}`;
141
+ }
142
+ /**
143
+ * Generate recommendation
144
+ */
145
+ generateRecommendation(churn, complexity, severity) {
146
+ const recommendations = [];
147
+ if (complexity.max > 20) {
148
+ recommendations.push('Reduce complexity by breaking down complex functions');
149
+ }
150
+ if (churn.commitCount > 30) {
151
+ recommendations.push('Stabilize this file - consider refactoring to reduce change frequency');
152
+ }
153
+ if (churn.authors.length > 8) {
154
+ recommendations.push('Establish clear ownership and coding standards');
155
+ }
156
+ if (complexity.average > 15) {
157
+ recommendations.push('Simplify logic and improve code structure');
158
+ }
159
+ if (recommendations.length === 0) {
160
+ recommendations.push('Monitor this file for further changes and consider refactoring');
161
+ }
162
+ const prefix = severity === 'CRITICAL' || severity === 'HIGH'
163
+ ? 'URGENT: '
164
+ : severity === 'MEDIUM'
165
+ ? 'Important: '
166
+ : '';
167
+ return prefix + recommendations.join('. ') + '.';
168
+ }
169
+ }
170
+ //# sourceMappingURL=hotspot-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hotspot-detector.js","sourceRoot":"","sources":["../../../src/analyzers/git/hotspot-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Git Integration Module
3
+ */
4
+ export { GitAnalyzer } from './git-analyzer.js';
5
+ export { ChurnCalculator } from './churn-calculator.js';
6
+ export { HotspotDetector } from './hotspot-detector.js';
7
+ export type { GitCommit, FileChurn, CodeHotspot, ContributorStats, GitAnalysisResult, GitAnalysisSummary, GitAnalysisOptions, } from './types.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Git Integration Module
3
+ */
4
+ export { GitAnalyzer } from './git-analyzer.js';
5
+ export { ChurnCalculator } from './churn-calculator.js';
6
+ export { HotspotDetector } from './hotspot-detector.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/git/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Git Integration Types
3
+ */
4
+ /**
5
+ * Git commit information
6
+ */
7
+ export interface GitCommit {
8
+ readonly hash: string;
9
+ readonly author: string;
10
+ readonly date: Date;
11
+ readonly message: string;
12
+ readonly filesChanged: ReadonlyArray<string>;
13
+ }
14
+ /**
15
+ * File churn metrics
16
+ */
17
+ export interface FileChurn {
18
+ readonly filePath: string;
19
+ readonly commitCount: number;
20
+ readonly additions: number;
21
+ readonly deletions: number;
22
+ readonly totalChurn: number;
23
+ readonly lastModified: Date;
24
+ readonly authors: ReadonlyArray<string>;
25
+ }
26
+ /**
27
+ * Code hotspot (high churn + high complexity)
28
+ */
29
+ export interface CodeHotspot {
30
+ readonly filePath: string;
31
+ readonly hotspotScore: number;
32
+ readonly churnScore: number;
33
+ readonly complexityScore: number;
34
+ readonly commitCount: number;
35
+ readonly totalChurn: number;
36
+ readonly averageComplexity: number;
37
+ readonly maxComplexity: number;
38
+ readonly severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
39
+ readonly reason: string;
40
+ readonly recommendation: string;
41
+ }
42
+ /**
43
+ * Contributor statistics
44
+ */
45
+ export interface ContributorStats {
46
+ readonly author: string;
47
+ readonly commitCount: number;
48
+ readonly filesChanged: number;
49
+ readonly linesAdded: number;
50
+ readonly linesDeleted: number;
51
+ readonly firstCommit: Date;
52
+ readonly lastCommit: Date;
53
+ }
54
+ /**
55
+ * Git analysis result
56
+ */
57
+ export interface GitAnalysisResult {
58
+ readonly hotspots: ReadonlyArray<CodeHotspot>;
59
+ readonly churnMetrics: ReadonlyArray<FileChurn>;
60
+ readonly contributors: ReadonlyArray<ContributorStats>;
61
+ readonly summary: GitAnalysisSummary;
62
+ readonly timestamp: Date;
63
+ }
64
+ /**
65
+ * Analysis summary
66
+ */
67
+ export interface GitAnalysisSummary {
68
+ readonly totalCommits: number;
69
+ readonly filesAnalyzed: number;
70
+ readonly hotspotCount: number;
71
+ readonly averageChurn: number;
72
+ readonly topContributor: string;
73
+ readonly dateRange: {
74
+ readonly from: Date;
75
+ readonly to: Date;
76
+ };
77
+ }
78
+ /**
79
+ * Analysis options
80
+ */
81
+ export interface GitAnalysisOptions {
82
+ readonly since?: string;
83
+ readonly until?: string;
84
+ readonly branch?: string;
85
+ readonly includePatterns?: readonly string[];
86
+ readonly excludePatterns?: readonly string[];
87
+ readonly hotspotThreshold?: number;
88
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Git Integration Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/git/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Halstead Complexity Calculator
3
+ *
4
+ * Calculates Halstead metrics from source code tokens
5
+ */
6
+ import type { HalsteadMetrics } from './types.js';
7
+ export declare class HalsteadCalculator {
8
+ private astParser;
9
+ constructor();
10
+ /**
11
+ * Calculate Halstead metrics for a file
12
+ */
13
+ calculateMetrics(filePath: string): HalsteadMetrics;
14
+ /**
15
+ * Compute Halstead metrics from counts
16
+ */
17
+ private computeMetrics;
18
+ /**
19
+ * Check if node is an operator
20
+ */
21
+ private isOperator;
22
+ /**
23
+ * Check if node is an operand
24
+ */
25
+ private isOperand;
26
+ /**
27
+ * Get operator symbol for syntax kind
28
+ */
29
+ private getOperatorSymbol;
30
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Halstead Complexity Calculator
3
+ *
4
+ * Calculates Halstead metrics from source code tokens
5
+ */
6
+ import { SyntaxKind } from 'ts-morph';
7
+ import { ASTParser } from '../ast/parser.js';
8
+ export class HalsteadCalculator {
9
+ astParser;
10
+ constructor() {
11
+ this.astParser = new ASTParser();
12
+ }
13
+ /**
14
+ * Calculate Halstead metrics for a file
15
+ */
16
+ calculateMetrics(filePath) {
17
+ const sourceFile = this.astParser.getSourceFile(filePath);
18
+ const operators = new Set();
19
+ const operands = new Set();
20
+ let operatorCount = 0;
21
+ let operandCount = 0;
22
+ // Traverse AST and count operators/operands
23
+ sourceFile.forEachDescendant((node) => {
24
+ const kind = node.getKind();
25
+ const text = node.getText();
26
+ // Operators
27
+ if (this.isOperator(kind)) {
28
+ operators.add(this.getOperatorSymbol(kind));
29
+ operatorCount++;
30
+ }
31
+ // Operands (identifiers, literals)
32
+ else if (this.isOperand(kind)) {
33
+ operands.add(text);
34
+ operandCount++;
35
+ }
36
+ });
37
+ const n1 = operators.size;
38
+ const n2 = operands.size;
39
+ const N1 = operatorCount;
40
+ const N2 = operandCount;
41
+ return this.computeMetrics(n1, n2, N1, N2);
42
+ }
43
+ /**
44
+ * Compute Halstead metrics from counts
45
+ */
46
+ computeMetrics(n1, n2, N1, N2) {
47
+ const vocabulary = n1 + n2;
48
+ const length = N1 + N2;
49
+ const calculatedLength = n1 > 0 && n2 > 0
50
+ ? n1 * Math.log2(n1) + n2 * Math.log2(n2)
51
+ : 0;
52
+ const volume = length > 0 && vocabulary > 0
53
+ ? length * Math.log2(vocabulary)
54
+ : 0;
55
+ const difficulty = n1 > 0 && n2 > 0 && N2 > 0
56
+ ? (n1 / 2) * (N2 / n2)
57
+ : 0;
58
+ const effort = difficulty * volume;
59
+ const time = effort / 18; // Seconds to program
60
+ const bugs = volume / 3000; // Estimated delivered bugs
61
+ return Object.freeze({
62
+ n1,
63
+ n2,
64
+ N1,
65
+ N2,
66
+ vocabulary,
67
+ length,
68
+ calculatedLength: Math.round(calculatedLength * 100) / 100,
69
+ volume: Math.round(volume * 100) / 100,
70
+ difficulty: Math.round(difficulty * 100) / 100,
71
+ effort: Math.round(effort * 100) / 100,
72
+ time: Math.round(time * 100) / 100,
73
+ bugs: Math.round(bugs * 1000) / 1000,
74
+ });
75
+ }
76
+ /**
77
+ * Check if node is an operator
78
+ */
79
+ isOperator(kind) {
80
+ const operators = [
81
+ SyntaxKind.PlusToken,
82
+ SyntaxKind.MinusToken,
83
+ SyntaxKind.AsteriskToken,
84
+ SyntaxKind.SlashToken,
85
+ SyntaxKind.PercentToken,
86
+ SyntaxKind.EqualsToken,
87
+ SyntaxKind.EqualsEqualsToken,
88
+ SyntaxKind.EqualsEqualsEqualsToken,
89
+ SyntaxKind.ExclamationEqualsToken,
90
+ SyntaxKind.ExclamationEqualsEqualsToken,
91
+ SyntaxKind.LessThanToken,
92
+ SyntaxKind.GreaterThanToken,
93
+ SyntaxKind.LessThanEqualsToken,
94
+ SyntaxKind.GreaterThanEqualsToken,
95
+ SyntaxKind.AmpersandAmpersandToken,
96
+ SyntaxKind.BarBarToken,
97
+ SyntaxKind.ExclamationToken,
98
+ SyntaxKind.QuestionToken,
99
+ SyntaxKind.PlusPlusToken,
100
+ SyntaxKind.MinusMinusToken,
101
+ SyntaxKind.AmpersandToken,
102
+ SyntaxKind.BarToken,
103
+ SyntaxKind.CaretToken,
104
+ SyntaxKind.TildeToken,
105
+ SyntaxKind.LessThanLessThanToken,
106
+ SyntaxKind.GreaterThanGreaterThanToken,
107
+ ];
108
+ return operators.includes(kind);
109
+ }
110
+ /**
111
+ * Check if node is an operand
112
+ */
113
+ isOperand(kind) {
114
+ return (kind === SyntaxKind.Identifier ||
115
+ kind === SyntaxKind.NumericLiteral ||
116
+ kind === SyntaxKind.StringLiteral ||
117
+ kind === SyntaxKind.TrueKeyword ||
118
+ kind === SyntaxKind.FalseKeyword ||
119
+ kind === SyntaxKind.NullKeyword);
120
+ }
121
+ /**
122
+ * Get operator symbol for syntax kind
123
+ */
124
+ getOperatorSymbol(kind) {
125
+ const symbols = {
126
+ [SyntaxKind.PlusToken]: '+',
127
+ [SyntaxKind.MinusToken]: '-',
128
+ [SyntaxKind.AsteriskToken]: '*',
129
+ [SyntaxKind.SlashToken]: '/',
130
+ [SyntaxKind.PercentToken]: '%',
131
+ [SyntaxKind.EqualsToken]: '=',
132
+ [SyntaxKind.EqualsEqualsToken]: '==',
133
+ [SyntaxKind.EqualsEqualsEqualsToken]: '===',
134
+ [SyntaxKind.ExclamationEqualsToken]: '!=',
135
+ [SyntaxKind.ExclamationEqualsEqualsToken]: '!==',
136
+ [SyntaxKind.LessThanToken]: '<',
137
+ [SyntaxKind.GreaterThanToken]: '>',
138
+ [SyntaxKind.LessThanEqualsToken]: '<=',
139
+ [SyntaxKind.GreaterThanEqualsToken]: '>=',
140
+ [SyntaxKind.AmpersandAmpersandToken]: '&&',
141
+ [SyntaxKind.BarBarToken]: '||',
142
+ [SyntaxKind.ExclamationToken]: '!',
143
+ [SyntaxKind.QuestionToken]: '?',
144
+ [SyntaxKind.PlusPlusToken]: '++',
145
+ [SyntaxKind.MinusMinusToken]: '--',
146
+ };
147
+ return symbols[kind] || kind.toString();
148
+ }
149
+ }
150
+ //# sourceMappingURL=halstead-calculator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"halstead-calculator.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/halstead-calculator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Advanced Metrics Analyzer
3
+ *
4
+ * Calculates Halstead metrics and Maintainability Index
5
+ */
6
+ export { MetricsAnalyzer } from './metrics-analyzer.js';
7
+ export { HalsteadCalculator } from './halstead-calculator.js';
8
+ export { MaintainabilityCalculator } from './maintainability-calculator.js';
9
+ export type { HalsteadMetrics, MaintainabilityIndex, FileMetrics, MetricsAnalysisResult, MetricsAnalysisOptions, MetricsSummary, } from './types.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Advanced Metrics Analyzer
3
+ *
4
+ * Calculates Halstead metrics and Maintainability Index
5
+ */
6
+ export { MetricsAnalyzer } from './metrics-analyzer.js';
7
+ export { HalsteadCalculator } from './halstead-calculator.js';
8
+ export { MaintainabilityCalculator } from './maintainability-calculator.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Maintainability Index Calculator
3
+ *
4
+ * Calculates MI = 171 - 5.2*ln(V) - 0.23*CC - 16.2*ln(LOC)
5
+ * Normalized to 0-100 scale
6
+ */
7
+ import type { MaintainabilityIndex } from './types.js';
8
+ export declare class MaintainabilityCalculator {
9
+ /**
10
+ * Calculate Maintainability Index
11
+ */
12
+ calculateIndex(halsteadVolume: number, cyclomaticComplexity: number, linesOfCode: number): MaintainabilityIndex;
13
+ /**
14
+ * Get letter rating from MI score
15
+ */
16
+ private getRating;
17
+ }