churn_vs_complexity 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/CLAUDE.md +60 -0
  4. data/lib/churn_vs_complexity/churn.rb +1 -1
  5. data/lib/churn_vs_complexity/cli/main.rb +8 -0
  6. data/lib/churn_vs_complexity/cli/parser.rb +68 -11
  7. data/lib/churn_vs_complexity/cli.rb +3 -1
  8. data/lib/churn_vs_complexity/complexity/go_calculator.rb +48 -0
  9. data/lib/churn_vs_complexity/complexity/python_calculator.rb +50 -0
  10. data/lib/churn_vs_complexity/complexity.rb +2 -0
  11. data/lib/churn_vs_complexity/complexity_validator.rb +4 -0
  12. data/lib/churn_vs_complexity/delta/config.rb +2 -2
  13. data/lib/churn_vs_complexity/delta.rb +8 -0
  14. data/lib/churn_vs_complexity/diff/checker.rb +46 -0
  15. data/lib/churn_vs_complexity/diff/config.rb +53 -0
  16. data/lib/churn_vs_complexity/diff/serializer.rb +78 -0
  17. data/lib/churn_vs_complexity/diff.rb +10 -0
  18. data/lib/churn_vs_complexity/file_selector.rb +26 -0
  19. data/lib/churn_vs_complexity/focus/checker.rb +59 -0
  20. data/lib/churn_vs_complexity/focus/config.rb +66 -0
  21. data/lib/churn_vs_complexity/focus/serializer.rb +98 -0
  22. data/lib/churn_vs_complexity/focus.rb +10 -0
  23. data/lib/churn_vs_complexity/gamma_score.rb +13 -0
  24. data/lib/churn_vs_complexity/gate/checker.rb +36 -0
  25. data/lib/churn_vs_complexity/gate/config.rb +53 -0
  26. data/lib/churn_vs_complexity/gate/serializer.rb +35 -0
  27. data/lib/churn_vs_complexity/gate.rb +10 -0
  28. data/lib/churn_vs_complexity/git_strategy.rb +13 -5
  29. data/lib/churn_vs_complexity/hotspots/checker.rb +17 -0
  30. data/lib/churn_vs_complexity/hotspots/config.rb +50 -0
  31. data/lib/churn_vs_complexity/hotspots/serializer.rb +49 -0
  32. data/lib/churn_vs_complexity/hotspots.rb +10 -0
  33. data/lib/churn_vs_complexity/language_validator.rb +3 -1
  34. data/lib/churn_vs_complexity/normal/config.rb +18 -0
  35. data/lib/churn_vs_complexity/normal/serializer/json.rb +36 -0
  36. data/lib/churn_vs_complexity/normal/serializer/summary_hash.rb +25 -32
  37. data/lib/churn_vs_complexity/normal/serializer.rb +1 -0
  38. data/lib/churn_vs_complexity/normal.rb +1 -1
  39. data/lib/churn_vs_complexity/risk_annotator.rb +26 -0
  40. data/lib/churn_vs_complexity/risk_classifier.rb +35 -0
  41. data/lib/churn_vs_complexity/triage/checker.rb +64 -0
  42. data/lib/churn_vs_complexity/triage/config.rb +52 -0
  43. data/lib/churn_vs_complexity/triage/serializer.rb +16 -0
  44. data/lib/churn_vs_complexity/triage.rb +10 -0
  45. data/lib/churn_vs_complexity/version.rb +1 -1
  46. data/lib/churn_vs_complexity.rb +8 -0
  47. data/tmp/test-support/delta/ruby-summary.txt +10 -5
  48. data/tmp/test-support/delta/ruby.csv +5 -5
  49. data/tmp/test-support/go/main.go +11 -0
  50. data/tmp/test-support/go/utils.go +13 -0
  51. data/tmp/test-support/python/example.py +6 -0
  52. data/tmp/test-support/python/utils.py +9 -0
  53. metadata +34 -3
@@ -7,45 +7,38 @@ module ChurnVsComplexity
7
7
  class << self
8
8
  def serialize(result)
9
9
  values_by_file = result[:values_by_file]
10
- churn_values = values_by_file.map { |_, values| values[0].to_f }
11
- complexity_values = values_by_file.map { |_, values| values[1].to_f }
12
-
13
- mean_churn = churn_values.sum / churn_values.size
14
- median_churn = churn_values.sort[churn_values.size / 2]
15
- mean_complexity = complexity_values.sum / complexity_values.size
16
- median_complexity = complexity_values.sort[complexity_values.size / 2]
10
+ end_date = result[:git_period].end_date
17
11
 
18
- max_churn = churn_values.max
19
- min_churn = churn_values.min
20
- max_complexity = complexity_values.max
21
- min_complexity = complexity_values.min
12
+ return empty_summary(end_date) if values_by_file.empty?
22
13
 
23
- epsilon = 0.0001
24
- gamma_score = values_by_file.map do |_, values|
25
- # unnormalised harmonic mean of churn and complexity,
26
- # since the summary needs to be comparable over time
27
- churn = values[0].to_f + epsilon
28
- complexity = values[1].to_f + epsilon
14
+ churn_values = values_by_file.map { |_, values| values[0].to_f }
15
+ complexity_values = values_by_file.map { |_, values| values[1].to_f }
16
+ gamma_scores = values_by_file.map { |_, values| GammaScore.calculate(values[0], values[1]) }
29
17
 
30
- (2 * churn * complexity) / (churn + complexity)
31
- end
18
+ stats(churn_values).transform_keys { |k| :"#{k}_churn" }
19
+ .merge(stats(complexity_values).transform_keys { |k| :"#{k}_complexity" })
20
+ .merge(stats(gamma_scores).slice(:mean, :median).transform_keys { |k| :"#{k}_gamma_score" })
21
+ .merge(end_date:)
22
+ end
32
23
 
33
- mean_gamma_score = gamma_score.sum / gamma_score.size
34
- median_gamma_score = gamma_score.sort[gamma_score.size / 2]
24
+ private
35
25
 
36
- end_date = result[:git_period].end_date
26
+ def stats(values)
27
+ { mean: values.sum / values.size, median: values.sort[values.size / 2], max: values.max, min: values.min }
28
+ end
37
29
 
30
+ def empty_summary(end_date)
38
31
  {
39
- mean_churn:,
40
- median_churn:,
41
- max_churn:,
42
- min_churn:,
43
- mean_complexity:,
44
- median_complexity:,
45
- max_complexity:,
46
- min_complexity:,
47
- mean_gamma_score:,
48
- median_gamma_score:,
32
+ mean_churn: 0.0,
33
+ median_churn: 0.0,
34
+ max_churn: 0.0,
35
+ min_churn: 0.0,
36
+ mean_complexity: 0.0,
37
+ median_complexity: 0.0,
38
+ max_complexity: 0.0,
39
+ min_complexity: 0.0,
40
+ mean_gamma_score: 0.0,
41
+ median_gamma_score: 0.0,
49
42
  end_date:,
50
43
  }
51
44
  end
@@ -5,6 +5,7 @@ require_relative 'serializer/summary'
5
5
  require_relative 'serializer/csv'
6
6
  require_relative 'serializer/graph'
7
7
  require_relative 'serializer/pass_through'
8
+ require_relative 'serializer/json'
8
9
 
9
10
  module ChurnVsComplexity
10
11
  module Normal
@@ -9,7 +9,7 @@ module ChurnVsComplexity
9
9
  module SerializerValidator
10
10
  def self.validate!(serializer:)
11
11
  raise ValidationError, "Unsupported serializer: #{serializer}" \
12
- unless %i[none csv graph summary].include?(serializer)
12
+ unless %i[none csv graph summary json].include?(serializer)
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChurnVsComplexity
4
+ module RiskAnnotator
5
+ def self.annotate(values_by_file, classifier: RiskClassifier.new)
6
+ values_by_file.map { |file, values| build_entry(file, values, classifier) }
7
+ end
8
+
9
+ def self.risk_summary(entries)
10
+ counts = entries.each_with_object(Hash.new(0)) { |e, acc| acc["#{e[:risk]}_risk"] += 1 }
11
+ { high_risk: counts['high_risk'], medium_risk: counts['medium_risk'], low_risk: counts['low_risk'] }
12
+ end
13
+
14
+ def self.build_entry(file, values, classifier)
15
+ gamma = GammaScore.calculate(values[0], values[1])
16
+ classification = classifier.classify(gamma_score: gamma)
17
+
18
+ {
19
+ file:, churn: values[0], complexity: values[1].to_f, gamma_score: gamma.round(2),
20
+ risk: classification[:risk], recommendation: classification[:recommendation],
21
+ }
22
+ end
23
+
24
+ private_class_method :build_entry
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChurnVsComplexity
4
+ class RiskClassifier
5
+ DEFAULT_LOW = 10
6
+ DEFAULT_HIGH = 25
7
+
8
+ RECOMMENDATIONS = {
9
+ 'low' => 'Safe for quick changes.',
10
+ 'medium' => 'Exercise judgement; consider tests for non-trivial changes.',
11
+ 'high' => 'Write tests before modifying. Consider multi-agent review.',
12
+ }.freeze
13
+
14
+ def initialize(low: DEFAULT_LOW, high: DEFAULT_HIGH)
15
+ @low = low
16
+ @high = high
17
+ end
18
+
19
+ def classify(gamma_score:)
20
+ risk = if gamma_score < @low
21
+ 'low'
22
+ elsif gamma_score > @high
23
+ 'high'
24
+ else
25
+ 'medium'
26
+ end
27
+
28
+ { risk:, recommendation: RECOMMENDATIONS[risk] }
29
+ end
30
+
31
+ def self.classify(gamma_score:)
32
+ new.classify(gamma_score:)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChurnVsComplexity
4
+ module Triage
5
+ class Checker
6
+ def initialize(language:, serializer:, targets:, since:, excluded:)
7
+ @language = language
8
+ @serializer = serializer
9
+ @targets = targets
10
+ @since = since
11
+ @excluded = excluded
12
+ end
13
+
14
+ def check(folder: nil)
15
+ files, dirs = partition_targets
16
+ folder = folder || dirs.first || '.'
17
+ engine = build_engine(files, folder)
18
+ raw_result = engine.check(folder:)
19
+ @serializer.serialize(raw_result)
20
+ end
21
+
22
+ private
23
+
24
+ def partition_targets
25
+ @targets.partition { |t| File.file?(t) }
26
+ end
27
+
28
+ def build_engine(files, _folder)
29
+ Engine.concurrent(
30
+ complexity: complexity_for(@language),
31
+ churn: Churn::GitCalculator,
32
+ file_selector: select_files(files),
33
+ serializer: Normal::Serializer::None,
34
+ since: @since,
35
+ )
36
+ end
37
+
38
+ def select_files(files)
39
+ selector = file_selector_for(@language)
40
+ files.any? ? selector.predefined(included: files, excluded: @excluded) : selector.excluding(@excluded)
41
+ end
42
+
43
+ def file_selector_for(language)
44
+ case language
45
+ when :ruby then FileSelector::Ruby
46
+ when :java then FileSelector::Java
47
+ when :javascript then FileSelector::JavaScript
48
+ when :python then FileSelector::Python
49
+ when :go then FileSelector::Go
50
+ end
51
+ end
52
+
53
+ def complexity_for(language)
54
+ case language
55
+ when :ruby then Complexity::FlogCalculator
56
+ when :java then Complexity::PMD::FolderCalculator
57
+ when :javascript then Complexity::ESLintCalculator
58
+ when :python then Complexity::PythonCalculator
59
+ when :go then Complexity::GoCalculator
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChurnVsComplexity
4
+ module Triage
5
+ class Config
6
+ def initialize(
7
+ language:,
8
+ serializer: :json,
9
+ targets: [],
10
+ since: nil,
11
+ excluded: [],
12
+ complexity_validator: ComplexityValidator,
13
+ since_validator: Normal::SinceValidator,
14
+ **options
15
+ )
16
+ @language = language
17
+ @serializer = serializer
18
+ @targets = targets
19
+ @since = since
20
+ @excluded = excluded
21
+ @complexity_validator = complexity_validator
22
+ @since_validator = since_validator
23
+ @options = options
24
+ end
25
+
26
+ def validate!
27
+ LanguageValidator.validate!(@language)
28
+ @since_validator.validate!(since: @since, relative_period: nil)
29
+ @complexity_validator.validate!(@language)
30
+ end
31
+
32
+ def checker
33
+ Checker.new(
34
+ language: @language,
35
+ serializer: triage_serializer,
36
+ targets: @targets,
37
+ since: @since,
38
+ excluded: @excluded,
39
+ )
40
+ end
41
+
42
+ private
43
+
44
+ def triage_serializer
45
+ case @serializer
46
+ when :json
47
+ Serializer::Json
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module ChurnVsComplexity
6
+ module Triage
7
+ module Serializer
8
+ module Json
9
+ def self.serialize(result)
10
+ entries = RiskAnnotator.annotate(result[:values_by_file])
11
+ JSON.generate({ files: entries, summary: RiskAnnotator.risk_summary(entries) })
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'triage/serializer'
4
+ require_relative 'triage/config'
5
+ require_relative 'triage/checker'
6
+
7
+ module ChurnVsComplexity
8
+ module Triage
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ChurnVsComplexity
4
- VERSION = '1.5.2'
4
+ VERSION = '1.6.0'
5
5
  end
@@ -32,6 +32,14 @@ require_relative 'churn_vs_complexity/git_date'
32
32
  require_relative 'churn_vs_complexity/complexity_validator'
33
33
  require_relative 'churn_vs_complexity/language_validator'
34
34
  require_relative 'churn_vs_complexity/git_strategy'
35
+ require_relative 'churn_vs_complexity/gamma_score'
36
+ require_relative 'churn_vs_complexity/risk_classifier'
37
+ require_relative 'churn_vs_complexity/risk_annotator'
35
38
  require_relative 'churn_vs_complexity/normal'
36
39
  require_relative 'churn_vs_complexity/timetravel'
37
40
  require_relative 'churn_vs_complexity/delta'
41
+ require_relative 'churn_vs_complexity/triage'
42
+ require_relative 'churn_vs_complexity/hotspots'
43
+ require_relative 'churn_vs_complexity/gate'
44
+ require_relative 'churn_vs_complexity/focus'
45
+ require_relative 'churn_vs_complexity/diff'
@@ -8,14 +8,16 @@ Type of change: modified
8
8
  Complexity: 58.34326171010786
9
9
 
10
10
  File, relative path: lib/churn_vs_complexity/serializer/timetravel/stats_calculator.rb
11
- Type of change: deleted
11
+ Type of change: new
12
+ Complexity: 80.35549194682164
12
13
 
13
14
  File, relative path: test/churn_vs_complexity/serializer/timetravel/quality_calculator_test.rb
14
15
  Type of change: modified
15
16
  Complexity: 13.054183368177016
16
17
 
17
18
  File, relative path: test/churn_vs_complexity/serializer/timetravel/stats_calculator_test.rb
18
- Type of change: deleted
19
+ Type of change: new
20
+ Complexity: 12.2198021565134
19
21
 
20
22
 
21
23
 
@@ -29,7 +31,8 @@ Type of change: modified
29
31
  Complexity: 70.26655854867414
30
32
 
31
33
  File, relative path: lib/churn_vs_complexity/serializer/pass_through.rb
32
- Type of change: deleted
34
+ Type of change: new
35
+ Complexity: 19.309088021254183
33
36
 
34
37
  File, relative path: lib/churn_vs_complexity/serializer/summary_hash.rb
35
38
  Type of change: modified
@@ -40,11 +43,13 @@ Type of change: modified
40
43
  Complexity: 131.0989019732436
41
44
 
42
45
  File, relative path: lib/churn_vs_complexity/serializer/timetravel/quality_calculator.rb
43
- Type of change: deleted
46
+ Type of change: new
47
+ Complexity: 23.324498016752965
44
48
 
45
49
  File, relative path: test/churn_vs_complexity/serializer/summary_hash_test.rb
46
50
  Type of change: modified
47
51
  Complexity: 14.396336540125482
48
52
 
49
53
  File, relative path: test/churn_vs_complexity/serializer/timetravel/quality_calculator_test.rb
50
- Type of change: deleted
54
+ Type of change: new
55
+ Complexity: 13.054183368177016
@@ -1,12 +1,12 @@
1
1
  Commit, Relative Path, Type of Change, Complexity
2
2
  b20a9bddd04afb9c7a736cf4530fd3188b5f785e, lib/churn_vs_complexity/serializer/timetravel.rb, modified, 58.34326171010786
3
- b20a9bddd04afb9c7a736cf4530fd3188b5f785e, lib/churn_vs_complexity/serializer/timetravel/stats_calculator.rb, deleted,
3
+ b20a9bddd04afb9c7a736cf4530fd3188b5f785e, lib/churn_vs_complexity/serializer/timetravel/stats_calculator.rb, new, 80.35549194682164
4
4
  b20a9bddd04afb9c7a736cf4530fd3188b5f785e, test/churn_vs_complexity/serializer/timetravel/quality_calculator_test.rb, modified, 13.054183368177016
5
- b20a9bddd04afb9c7a736cf4530fd3188b5f785e, test/churn_vs_complexity/serializer/timetravel/stats_calculator_test.rb, deleted,
5
+ b20a9bddd04afb9c7a736cf4530fd3188b5f785e, test/churn_vs_complexity/serializer/timetravel/stats_calculator_test.rb, new, 12.2198021565134
6
6
  4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/config.rb, modified, 70.26655854867414
7
- 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/pass_through.rb, deleted,
7
+ 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/pass_through.rb, new, 19.309088021254183
8
8
  4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/summary_hash.rb, modified, 89.25682464940157
9
9
  4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/timetravel.rb, modified, 131.0989019732436
10
- 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/timetravel/quality_calculator.rb, deleted,
10
+ 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, lib/churn_vs_complexity/serializer/timetravel/quality_calculator.rb, new, 23.324498016752965
11
11
  4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, test/churn_vs_complexity/serializer/summary_hash_test.rb, modified, 14.396336540125482
12
- 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, test/churn_vs_complexity/serializer/timetravel/quality_calculator_test.rb, deleted,
12
+ 4f3151f83e982eb8f2b8a4e7a7572a0af156c3c0, test/churn_vs_complexity/serializer/timetravel/quality_calculator_test.rb, new, 13.054183368177016
@@ -0,0 +1,11 @@
1
+ package main
2
+
3
+ import "fmt"
4
+
5
+ func main() {
6
+ fmt.Println("Hello, world!")
7
+ }
8
+
9
+ func add(a, b int) int {
10
+ return a + b
11
+ }
@@ -0,0 +1,13 @@
1
+ package main
2
+
3
+ func calculateSum(numbers []int) int {
4
+ total := 0
5
+ for _, n := range numbers {
6
+ total += n
7
+ }
8
+ return total
9
+ }
10
+
11
+ func isEven(n int) bool {
12
+ return n%2 == 0
13
+ }
@@ -0,0 +1,6 @@
1
+ def hello():
2
+ print("Hello, world!")
3
+
4
+
5
+ def add(a, b):
6
+ return a + b
@@ -0,0 +1,9 @@
1
+ def calculate_sum(numbers):
2
+ total = 0
3
+ for n in numbers:
4
+ total += n
5
+ return total
6
+
7
+
8
+ def is_even(n):
9
+ return n % 2 == 0
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: churn_vs_complexity
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik T. Madsen
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-10-21 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: flog
@@ -52,6 +52,7 @@ files:
52
52
  - ".devcontainer/devcontainer.json"
53
53
  - ".rubocop.yml"
54
54
  - CHANGELOG.md
55
+ - CLAUDE.md
55
56
  - Dockerfile
56
57
  - Dockerfile.dev
57
58
  - LICENSE.txt
@@ -67,9 +68,11 @@ files:
67
68
  - lib/churn_vs_complexity/complexity.rb
68
69
  - lib/churn_vs_complexity/complexity/eslint_calculator.rb
69
70
  - lib/churn_vs_complexity/complexity/flog_calculator.rb
71
+ - lib/churn_vs_complexity/complexity/go_calculator.rb
70
72
  - lib/churn_vs_complexity/complexity/pmd.rb
71
73
  - lib/churn_vs_complexity/complexity/pmd/files_calculator.rb
72
74
  - lib/churn_vs_complexity/complexity/pmd/folder_calculator.rb
75
+ - lib/churn_vs_complexity/complexity/python_calculator.rb
73
76
  - lib/churn_vs_complexity/complexity_validator.rb
74
77
  - lib/churn_vs_complexity/concurrent_calculator.rb
75
78
  - lib/churn_vs_complexity/delta.rb
@@ -80,19 +83,39 @@ files:
80
83
  - lib/churn_vs_complexity/delta/factory.rb
81
84
  - lib/churn_vs_complexity/delta/multi_checker.rb
82
85
  - lib/churn_vs_complexity/delta/serializer.rb
86
+ - lib/churn_vs_complexity/diff.rb
87
+ - lib/churn_vs_complexity/diff/checker.rb
88
+ - lib/churn_vs_complexity/diff/config.rb
89
+ - lib/churn_vs_complexity/diff/serializer.rb
83
90
  - lib/churn_vs_complexity/engine.rb
84
91
  - lib/churn_vs_complexity/file_selector.rb
92
+ - lib/churn_vs_complexity/focus.rb
93
+ - lib/churn_vs_complexity/focus/checker.rb
94
+ - lib/churn_vs_complexity/focus/config.rb
95
+ - lib/churn_vs_complexity/focus/serializer.rb
96
+ - lib/churn_vs_complexity/gamma_score.rb
97
+ - lib/churn_vs_complexity/gate.rb
98
+ - lib/churn_vs_complexity/gate/checker.rb
99
+ - lib/churn_vs_complexity/gate/config.rb
100
+ - lib/churn_vs_complexity/gate/serializer.rb
85
101
  - lib/churn_vs_complexity/git_date.rb
86
102
  - lib/churn_vs_complexity/git_strategy.rb
103
+ - lib/churn_vs_complexity/hotspots.rb
104
+ - lib/churn_vs_complexity/hotspots/checker.rb
105
+ - lib/churn_vs_complexity/hotspots/config.rb
106
+ - lib/churn_vs_complexity/hotspots/serializer.rb
87
107
  - lib/churn_vs_complexity/language_validator.rb
88
108
  - lib/churn_vs_complexity/normal.rb
89
109
  - lib/churn_vs_complexity/normal/config.rb
90
110
  - lib/churn_vs_complexity/normal/serializer.rb
91
111
  - lib/churn_vs_complexity/normal/serializer/csv.rb
92
112
  - lib/churn_vs_complexity/normal/serializer/graph.rb
113
+ - lib/churn_vs_complexity/normal/serializer/json.rb
93
114
  - lib/churn_vs_complexity/normal/serializer/pass_through.rb
94
115
  - lib/churn_vs_complexity/normal/serializer/summary.rb
95
116
  - lib/churn_vs_complexity/normal/serializer/summary_hash.rb
117
+ - lib/churn_vs_complexity/risk_annotator.rb
118
+ - lib/churn_vs_complexity/risk_classifier.rb
96
119
  - lib/churn_vs_complexity/timetravel.rb
97
120
  - lib/churn_vs_complexity/timetravel/config.rb
98
121
  - lib/churn_vs_complexity/timetravel/factory.rb
@@ -101,6 +124,10 @@ files:
101
124
  - lib/churn_vs_complexity/timetravel/serializer/stats_calculator.rb
102
125
  - lib/churn_vs_complexity/timetravel/traveller.rb
103
126
  - lib/churn_vs_complexity/timetravel/worktree.rb
127
+ - lib/churn_vs_complexity/triage.rb
128
+ - lib/churn_vs_complexity/triage/checker.rb
129
+ - lib/churn_vs_complexity/triage/config.rb
130
+ - lib/churn_vs_complexity/triage/serializer.rb
104
131
  - lib/churn_vs_complexity/version.rb
105
132
  - package-lock.json
106
133
  - tmp/eslint-support/complexity-calculator.js
@@ -110,12 +137,16 @@ files:
110
137
  - tmp/template/timetravel_graph.html
111
138
  - tmp/test-support/delta/ruby-summary.txt
112
139
  - tmp/test-support/delta/ruby.csv
140
+ - tmp/test-support/go/main.go
141
+ - tmp/test-support/go/utils.go
113
142
  - tmp/test-support/java/small-example/src/main/java/org/example/Main.java
114
143
  - tmp/test-support/java/small-example/src/main/java/org/example/spice/Checker.java
115
144
  - tmp/test-support/javascript/complex.js
116
145
  - tmp/test-support/javascript/moderate.js
117
146
  - tmp/test-support/javascript/simple.js
118
147
  - tmp/test-support/javascript/typescript-example.ts
148
+ - tmp/test-support/python/example.py
149
+ - tmp/test-support/python/utils.py
119
150
  - tmp/test-support/txt/abc.txt
120
151
  - tmp/test-support/txt/d.txt
121
152
  - tmp/test-support/txt/ef.txt
@@ -148,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
179
  - !ruby/object:Gem::Version
149
180
  version: '0'
150
181
  requirements: []
151
- rubygems_version: 3.6.0.dev
182
+ rubygems_version: 3.6.7
152
183
  specification_version: 4
153
184
  summary: A tool to visualise code complexity in projects and help direct refactoring
154
185
  efforts.