reviewer 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.alexignore +1 -0
  3. data/.github/workflows/main.yml +5 -3
  4. data/.reviewer.example.yml +20 -10
  5. data/.reviewer.future.yml +221 -0
  6. data/.reviewer.yml +45 -8
  7. data/.reviewer_stdout +0 -0
  8. data/.rubocop.yml +1 -0
  9. data/Gemfile.lock +29 -28
  10. data/LICENSE.txt +4 -20
  11. data/README.md +26 -7
  12. data/lib/reviewer/arguments/files.rb +14 -8
  13. data/lib/reviewer/arguments/keywords.rb +5 -2
  14. data/lib/reviewer/arguments/tags.rb +11 -4
  15. data/lib/reviewer/arguments.rb +11 -4
  16. data/lib/reviewer/batch.rb +41 -14
  17. data/lib/reviewer/command/string/env.rb +4 -0
  18. data/lib/reviewer/command/string/flags.rb +12 -1
  19. data/lib/reviewer/command/string.rb +12 -18
  20. data/lib/reviewer/command.rb +7 -32
  21. data/lib/reviewer/configuration.rb +8 -1
  22. data/lib/reviewer/conversions.rb +0 -11
  23. data/lib/reviewer/guidance.rb +9 -5
  24. data/lib/reviewer/history.rb +32 -1
  25. data/lib/reviewer/keywords/git/staged.rb +16 -0
  26. data/lib/reviewer/output/printer.rb +44 -0
  27. data/lib/reviewer/output/scrubber.rb +48 -0
  28. data/lib/reviewer/output/token.rb +85 -0
  29. data/lib/reviewer/output.rb +73 -43
  30. data/lib/reviewer/runner/strategies/captured.rb +157 -0
  31. data/lib/reviewer/runner/strategies/{verbose.rb → passthrough.rb} +13 -13
  32. data/lib/reviewer/runner.rb +71 -13
  33. data/lib/reviewer/shell/result.rb +22 -7
  34. data/lib/reviewer/shell/timer.rb +15 -0
  35. data/lib/reviewer/shell.rb +7 -11
  36. data/lib/reviewer/tool/settings.rb +12 -5
  37. data/lib/reviewer/tool.rb +25 -3
  38. data/lib/reviewer/version.rb +1 -1
  39. data/lib/reviewer.rb +11 -10
  40. data/reviewer.gemspec +9 -5
  41. data/structure.svg +1 -0
  42. metadata +34 -28
  43. data/.ruby-version +0 -1
  44. data/lib/reviewer/command/string/verbosity.rb +0 -51
  45. data/lib/reviewer/command/verbosity.rb +0 -65
  46. data/lib/reviewer/printer.rb +0 -25
  47. data/lib/reviewer/runner/strategies/quiet.rb +0 -90
@@ -18,26 +18,37 @@ module Reviewer
18
18
  executable_not_found: "can't find executable"
19
19
  }.freeze
20
20
 
21
- attr_accessor :stdout, :stderr, :exit_status
21
+ attr_accessor :stdout, :stderr, :status, :exit_status
22
22
 
23
- # An instance of a result from running a local command
23
+ # An instance of a result from running a local command. Captures the values for `$stdout`,
24
+ # `$stderr`, and the exit status of the command to provide a reliable way of interpreting
25
+ # the results for commands that otherwise use these values inconsistently.
24
26
  # @param stdout = nil [String] standard out output from a command
25
27
  # @param stderr = nil [String] standard error output from a command
26
28
  # @param status = nil [ProcessStatus] an instance of ProcessStatus for a command
27
29
  #
28
- # @return [Shell::Result] result from running a command-line command
30
+ # @example Using with `Open3.capture3`
31
+ # captured_results = Open3.capture3(command)
32
+ # result = Result.new(*captured_results)
33
+ #
34
+ # @return [self]
29
35
  def initialize(stdout = nil, stderr = nil, status = nil)
30
36
  @stdout = stdout
31
37
  @stderr = stderr
38
+ @status = status
32
39
  @exit_status = status&.exitstatus
33
40
  end
34
41
 
35
- # Determines whether re-running a command is entirely futile. Primarily to help when a command
42
+ def exists?
43
+ [stdout, stderr, exit_status].compact.any?
44
+ end
45
+
46
+ # Determines if re-running a command is entirely futile. Primarily to help when a command
36
47
  # fails within a batch and needs to be re-run to show the output
37
48
  #
38
49
  # @return [Boolean] true if the exit status code is greater than or equal to 126
39
- def total_failure?
40
- exit_status >= EXIT_STATUS_CODES[:cannot_execute]
50
+ def rerunnable?
51
+ exit_status < EXIT_STATUS_CODES[:cannot_execute]
41
52
  end
42
53
 
43
54
  # Determines whether a command simply cannot be executed.
@@ -62,7 +73,11 @@ module Reviewer
62
73
  #
63
74
  # @return [String] stdout if present, otherwise stderr
64
75
  def to_s
65
- stderr.strip.empty? ? stdout : stderr
76
+ result_string = ''
77
+ result_string += stderr
78
+ result_string += stdout
79
+
80
+ result_string.strip
66
81
  end
67
82
  end
68
83
  end
@@ -8,15 +8,30 @@ module Reviewer
8
8
  class Timer
9
9
  attr_accessor :prep, :main
10
10
 
11
+ # A 'Smart' timer that understands preparation time and main time and can easily do the math
12
+ # to help determine what percentage of time was prep. The times can be passed in directly or
13
+ # recorded using the `record_prep` and `record_main` methods
14
+ # @param prep: nil [Float] the amount of time in seconds the preparation command ran
15
+ # @param main: nil [Float] the amount of time in seconds the primary command ran
16
+ #
17
+ # @return [self]
11
18
  def initialize(prep: nil, main: nil)
12
19
  @prep = prep
13
20
  @main = main
14
21
  end
15
22
 
23
+ # Records the execution time for the block and assigns it to the `prep` time
24
+ # @param &block [Block] the commands to be timed
25
+ #
26
+ # @return [Float] the execution time for the preparation
16
27
  def record_prep(&block)
17
28
  @prep = record(&block)
18
29
  end
19
30
 
31
+ # Records the execution time for the block and assigns it to the `main` time
32
+ # @param &block [Block] the commands to be timed
33
+ #
34
+ # @return [Float] the execution time for the main command
20
35
  def record_main(&block)
21
36
  @main = record(&block)
22
37
  end
@@ -10,7 +10,7 @@ module Reviewer
10
10
  class Shell
11
11
  extend Forwardable
12
12
 
13
- attr_reader :timer, :result
13
+ attr_reader :timer, :result, :captured_results
14
14
 
15
15
  def_delegators :@result, :exit_status
16
16
 
@@ -22,14 +22,16 @@ module Reviewer
22
22
  @result = Result.new
23
23
  end
24
24
 
25
- # Run a command without capturing the output. This ensures the results are displayed the same as
25
+ # Run a command without capturing the output. This ensures the results are displayed realtime
26
26
  # if the command was run directly in the shell. So it keeps any color or other formatting that
27
27
  # would be stripped out by capturing $stdout as a basic string.
28
28
  # @param command [String] the command to run
29
29
  #
30
30
  # @return [Integer] exit status vaue of 0 when successful or 1 when unsuccessful
31
31
  def direct(command)
32
- result.exit_status = print_results(command) ? 0 : 1
32
+ command = String(command)
33
+
34
+ result.exit_status = system(command) ? 0 : 1
33
35
  end
34
36
 
35
37
  def capture_prep(command)
@@ -45,14 +47,8 @@ module Reviewer
45
47
  def capture_results(command)
46
48
  command = String(command)
47
49
 
48
- captured_results = Open3.capture3(command)
49
- @result = Result.new(*captured_results)
50
- end
51
-
52
- def print_results(command)
53
- command = String(command)
54
-
55
- system(command)
50
+ @captured_results = Open3.capture3(command)
51
+ @result = Result.new(*@captured_results)
56
52
  end
57
53
  end
58
54
  end
@@ -2,12 +2,17 @@
2
2
 
3
3
  module Reviewer
4
4
  class Tool
5
- # Converts/casts tool configuration values and provides default values if not set.
5
+ # Converts/casts tool configuration values and provides appropriate default values if not set.
6
6
  class Settings
7
7
  attr_reader :tool_key, :config
8
8
 
9
9
  alias key tool_key
10
10
 
11
+ # Creates an instance of settings for retrieving values from the configuration file.
12
+ # @param tool_key [Symbol] the unique identifier for the tool in the config file
13
+ # @param config: nil [Hash] the configuration values to examine for the settings
14
+ #
15
+ # @return [self]
11
16
  def initialize(tool_key, config: nil)
12
17
  @tool_key = tool_key.to_sym
13
18
  @config = config || load_config
@@ -55,18 +60,20 @@ module Reviewer
55
60
  config.fetch(:flags) { {} }
56
61
  end
57
62
 
63
+ # The collection of configured commands for the tool
64
+ #
65
+ # @return [Hash] all of the commands configured for the tool
58
66
  def commands
59
67
  config.fetch(:commands) { {} }
60
68
  end
61
69
 
70
+ # The largest exit status that can still be considered a success for the command
71
+ #
72
+ # @return [Integer] the configured `max_exit_status` for the tool or 0 if one isn't configured
62
73
  def max_exit_status
63
74
  commands.fetch(:max_exit_status, 0)
64
75
  end
65
76
 
66
- def quiet_option
67
- commands.fetch(:quiet_option, '')
68
- end
69
-
70
77
  protected
71
78
 
72
79
  def state
data/lib/reviewer/tool.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'date'
4
+
3
5
  require_relative 'tool/settings'
4
6
 
5
7
  module Reviewer
@@ -87,9 +89,11 @@ module Reviewer
87
89
 
88
90
  # Specifies when the tool last had it's `prepare` command run
89
91
  #
90
- # @return [DateTime] timestamp of when the `prepare` command was last run
92
+ # @return [Time] timestamp of when the `prepare` command was last run
91
93
  def last_prepared_at
92
- Reviewer.history.get(key, :last_prepared_at)
94
+ date_string = Reviewer.history.get(key, :last_prepared_at)
95
+
96
+ date_string == '' || date_string.nil? ? nil : DateTime.parse(date_string).to_time
93
97
  end
94
98
 
95
99
  # Sets the timestamp for when the tool last ran its `prepare` command
@@ -97,7 +101,25 @@ module Reviewer
97
101
  #
98
102
  # @return [DateTime] timestamp of when the `prepare` command was last run
99
103
  def last_prepared_at=(last_prepared_at)
100
- Reviewer.history.set(key, :last_prepared_at, last_prepared_at)
104
+ Reviewer.history.set(key, :last_prepared_at, last_prepared_at.to_s)
105
+ end
106
+
107
+ def average_time(command)
108
+ times = get_timing(command)
109
+
110
+ times.any? ? times.sum / times.size : 0
111
+ end
112
+
113
+ def get_timing(command)
114
+ Reviewer.history.get(key, command.raw_string) || []
115
+ end
116
+
117
+ def record_timing(command, time)
118
+ return if time.nil?
119
+
120
+ timing = get_timing(command).take(4) << time.round(2)
121
+
122
+ Reviewer.history.set(key, command.raw_string, timing)
101
123
  end
102
124
 
103
125
  # Determines whether the `prepare` command was run recently enough
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reviewer
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.5'
5
5
  end
data/lib/reviewer.rb CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'benchmark'
4
4
  require 'forwardable'
5
- require 'logger'
5
+ # require 'logger'
6
+ require 'rainbow'
6
7
 
7
8
  require_relative 'reviewer/conversions'
8
9
 
@@ -15,7 +16,6 @@ require_relative 'reviewer/history'
15
16
  require_relative 'reviewer/keywords'
16
17
  require_relative 'reviewer/loader'
17
18
  require_relative 'reviewer/output'
18
- require_relative 'reviewer/printer'
19
19
  require_relative 'reviewer/runner'
20
20
  require_relative 'reviewer/shell'
21
21
  require_relative 'reviewer/tool'
@@ -33,8 +33,8 @@ module Reviewer
33
33
  end
34
34
 
35
35
  # Runs the `review` command for the specified tools/files. Reviewer expects all configured
36
- # commands that are not disabled to have an entry for the `review` command.
37
- # @param clear_streen [boolean] clears the screen to reduce noise when true
36
+ # commands that are not disabled to have an entry for the `review` command.
37
+ # @param clear_screen [boolean] clears the screen to reduce noise when true
38
38
  #
39
39
  # @return [void] Prints output to the console
40
40
  def review(clear_screen: false)
@@ -42,7 +42,7 @@ module Reviewer
42
42
  end
43
43
 
44
44
  # Runs the `format` command for the specified tools/files for which it is configured.
45
- # @param clear_streen [boolean] clears the screen to reduce noise when true
45
+ # @param clear_screen [boolean] clears the screen to reduce noise when true
46
46
  #
47
47
  # @return [void] Prints output to the console
48
48
  def format(clear_screen: false)
@@ -57,7 +57,7 @@ module Reviewer
57
57
  end
58
58
 
59
59
  # An interface for the collection of configured tools for accessing subsets of tools
60
- # based on enabled/disabled, tags, keywords, etc.
60
+ # based on enabled/disabled, tags, keywords, etc.
61
61
  #
62
62
  # @return [Reviewer::Tools] exposes the set of tools to be run in a given context
63
63
  def tools
@@ -65,7 +65,7 @@ module Reviewer
65
65
  end
66
66
 
67
67
  # The primary output method for Reviewer to consistently display success/failure details for a
68
- # unique run of each tool and the collective summary when relevant.
68
+ # unique run of each tool and the collective summary when relevant.
69
69
  #
70
70
  # @return [Reviewer::Output] prints formatted output to the console.
71
71
  def output
@@ -101,17 +101,18 @@ module Reviewer
101
101
  private
102
102
 
103
103
  # Provides a consistent approach to running and benchmarking commmands and preventing further
104
- # execution of later tools if a command fails.
104
+ # execution of later tools if a command fails.
105
105
  # @param command_type [Symbol] the specific command to run for each tool
106
+ # @param clear_screen [Boolean] if true, clears the screen before a run
106
107
  #
107
108
  # @example Run the `review` command for each relevant tool
108
109
  # perform(:review)
109
110
  #
110
111
  # @return [Hash] the exit status (in integer format) for each command run
111
112
  def perform(command_type, clear_screen: false)
112
- system('clear') if clear_screen
113
+ output.clear if clear_screen
113
114
 
114
- results = Batch.run(command_type, tools.current)
115
+ results = Batch.new(command_type, tools.current).run
115
116
 
116
117
  # Return the largest exit status
117
118
  exit results.values.max
data/reviewer.gemspec CHANGED
@@ -15,8 +15,12 @@ Gem::Specification.new do |spec|
15
15
  spec.required_ruby_version = Gem::Requirement.new('>= 2.5.9')
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
- spec.metadata['source_code_uri'] = 'https://github.com/garrettdimon/reviewer'
18
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/garrettdimon/reviewer/issues'
19
19
  spec.metadata['changelog_uri'] = 'https://github.com/garrettdimon/reviewer/CHANGELOG.md'
20
+ spec.metadata['documentation_uri'] = 'https://www.rubydoc.info/gems/reviewer'
21
+ spec.metadata['source_code_uri'] = 'https://github.com/garrettdimon/reviewer'
22
+ spec.metadata['wiki_uri'] = 'https://github.com/garrettdimon/reviewer/wiki'
23
+ spec.metadata['rubygems_mfa_required'] = 'true'
20
24
 
21
25
  # Specify which files should be added to the gem when it is released.
22
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -27,21 +31,21 @@ Gem::Specification.new do |spec|
27
31
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
32
  spec.require_paths = ['lib']
29
33
 
30
- spec.add_dependency 'colorize'
34
+ spec.add_dependency 'rainbow'
31
35
  spec.add_dependency 'slop'
32
36
 
33
37
  spec.add_development_dependency 'bundler-audit'
34
38
  spec.add_development_dependency 'codecov'
35
- spec.add_development_dependency 'dead_end'
36
39
  spec.add_development_dependency 'flay'
37
40
  spec.add_development_dependency 'flog'
38
41
  spec.add_development_dependency 'inch'
39
42
  spec.add_development_dependency 'minitest'
40
- spec.add_development_dependency 'minitest-color'
41
- spec.add_development_dependency 'psych', '~> 3.3.2'
43
+ spec.add_development_dependency 'minitest-heat'
44
+ spec.add_development_dependency 'psych'
42
45
  spec.add_development_dependency 'reek'
43
46
  spec.add_development_dependency 'rubocop'
44
47
  spec.add_development_dependency 'rubocop-minitest'
45
48
  spec.add_development_dependency 'rubocop-rake'
46
49
  spec.add_development_dependency 'simplecov'
50
+ spec.add_development_dependency 'yard'
47
51
  end
data/structure.svg ADDED
@@ -0,0 +1 @@
1
+ <svg width="1000" height="1000" style="background:white;font-family:sans-serif;overflow:visible" xmlns="http://www.w3.org/2000/svg"><defs><filter id="glow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="4" result="coloredBlur"></feGaussianBlur><feMerge><feMergeNode in="coloredBlur"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></defs><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(458.1684758396736, 402.8013409019584)"><circle r="352.40190201003946" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(520.8364435594557, 806.4990877668961)"><circle r="36.11178860447648" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(409.6517236116371, 402.8013409019584)"><circle r="294.1473077312859" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(757.1847045963179, 402.8013409019584)"><circle style="transition:all 0.5s ease-out" r="43.64783120267789" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(687.4299657134559, 856.9423846447222)"><circle style="transition:all 0.5s ease-out" r="51.31612086796417" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(788.9846757350268, 859.3421087760426)"><circle style="transition:all 0.5s ease-out" r="46.2472197118418" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(726.4250919182904, 947.0721172937218)"><circle style="transition:all 0.5s ease-out" r="42.86782312801615" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(726.687090398783, 755.9238323654778)"><circle style="transition:all 0.5s ease-out" r="35.01102176297566" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(656.2776843121794, 774.053081197875)"><circle style="transition:all 0.5s ease-out" r="34.05582985803832" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(646.3075304917123, 935.5086582680074)"><circle style="transition:all 0.5s ease-out" r="33.36112099562045" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(792.4478568898579, 778.7047877445898)"><circle style="transition:all 0.5s ease-out" r="30.75334019375212" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(795.2808076405827, 932.7721040738809)"><circle style="transition:all 0.5s ease-out" r="23.450700366199015" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(628.2012046638729, 818.8498773291199)"><circle style="transition:all 0.5s ease-out" r="15.087376074028514" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(625.1052165805941, 879.58232371161)"><circle style="transition:all 0.5s ease-out" r="10.993857902246123" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(759.9605608023857, 807.5923921321375)"><circle style="transition:all 0.5s ease-out" r="9.032375950599938" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(740.4589615675088, 893.1073074759857)"><circle style="transition:all 0.5s ease-out" r="8.891894979240078" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(697.4389756167642, 792.4331053326879)"><circle style="transition:all 0.5s ease-out" r="7.7087773473446" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#FFC312;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(739.3959953779754, 800.9150363761469)"><circle style="transition:all 0.5s ease-out" r="7.6760435377025455" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(754.6373603648877, 899.7098713097646)"><circle style="transition:all 0.5s ease-out" r="2.7484644755615304" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(688.9313125250869, 914.8390531135157)"><circle style="transition:all 0.5s ease-out" r="2.5586811792341817" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(506.1084751770936, 806.4990877668961)"><circle style="transition:all 0.5s ease-out" r="16.95752838087938" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(540.0071178609526, 806.4990877668961)"><circle style="transition:all 0.5s ease-out" r="12.514822461744519" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(355.4184691733666, 395.8977440745981)"><circle style="transition:all 0.5s ease-out" r="48.297958480594644" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(453.66003516638904, 395.8977440745981)"><circle style="transition:all 0.5s ease-out" r="45.517315671192776" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(407.83945742807794, 501.6014766854548)"><circle r="65.2640503586534" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(408.44899912286195, 266.8449117959501)"><circle r="86.7994775020254" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(277.6542041828907, 480.50667705487933)"><circle r="62.19290440091251" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(578.9817228671643, 482.6836693665573)"><circle r="102.49432161596253" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(231.7281199383259, 318.8649338109235)"><circle r="92.99244862172178" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(523.1975630378445, 335.21636724206417)"><circle style="transition:all 0.5s ease-out" r="42.347764114422745" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(176.26520220161186, 445.3500189745872)"><circle style="transition:all 0.5s ease-out" r="40.692128091001564" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(605.0441527585806, 342.75082556501854)"><circle style="transition:all 0.5s ease-out" r="35.41859767673708" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(327.59590900349434, 569.4790692623358)"><circle style="transition:all 0.5s ease-out" r="35.41148765003155" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(534.3474887230652, 253.8625225793911)"><circle style="transition:all 0.5s ease-out" r="35.34030870841474" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(476.4643386600166, 578.911911443936)"><circle style="transition:all 0.5s ease-out" r="33.68411134954049" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(299.4858839094448, 207.73782607508076)"><circle style="transition:all 0.5s ease-out" r="32.73635414382169" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(390.0098532010105, 598.7827521061267)"><circle style="transition:all 0.5s ease-out" r="29.11297292304826" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(440.3851018289799, 634.7060029474101)"><circle style="transition:all 0.5s ease-out" r="28.332745267196174" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(598.6034010548337, 275.2555582441296)"><circle style="transition:all 0.5s ease-out" r="27.956986512323546" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(502.704659203589, 194.16981738111775)"><circle style="transition:all 0.5s ease-out" r="27.79439199698623" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(266.51867408166913, 567.6833977935446)"><circle style="transition:all 0.5s ease-out" r="21.265846110817378" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(346.18721110272986, 174.45592016501854)"><circle style="transition:all 0.5s ease-out" r="20.184535485530812" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(523.0058458149439, 583.8411735366119)"><circle style="transition:all 0.5s ease-out" r="8.691407810834628" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(351.1758829983302, 609.7245028990388)"><circle style="transition:all 0.5s ease-out" r="6.806728247623728" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(383.5814103897357, 501.6014766854548)"><circle style="transition:all 0.5s ease-out" r="36.57971147907614" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(446.6323148277716, 501.6014766854548)"><circle style="transition:all 0.5s ease-out" r="22.044901117724688" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(370.84570420293034, 266.8449117959501)"><circle style="transition:all 0.5s ease-out" r="44.76989074085872" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(455.4320357843382, 266.8449117959501)"><circle style="transition:all 0.5s ease-out" r="35.39014899931409" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(265.3052220935813, 480.50667705487933)"><circle style="transition:all 0.5s ease-out" r="45.41763047036804" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(325.2849805738762, 480.50667705487933)"><circle style="transition:all 0.5s ease-out" r="10.135836168691887" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(544.5152135162864, 471.920566006636)"><circle r="61.960071361511915" style="transition:all 0.5s ease-out" stroke="#290819" opacity="0.2" stroke-width="1" fill="none"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(643.5300677882587, 471.920566006636)"><circle style="transition:all 0.5s ease-out" r="32.62849106922531" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(618.710163320952, 535.9504578797049)"><circle style="transition:all 0.5s ease-out" r="31.617298105357957" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(191.4503126965002, 309.1431465377067)"><circle style="transition:all 0.5s ease-out" r="47.13169160962506" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(281.17799339890166, 309.1431465377067)"><circle style="transition:all 0.5s ease-out" r="38.16969725154132" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(244.21679860063716, 373.9896454048579)"><circle style="transition:all 0.5s ease-out" r="32.04447135758986" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(519.6457545955952, 464.8290172745834)"><circle style="transition:all 0.5s ease-out" r="31.672997427945933" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(578.5313449242576, 464.8290172745834)"><circle style="transition:all 0.5s ease-out" r="22.78630105948141" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(556.9214342696687, 507.08309517374425)"><circle style="transition:all 0.5s ease-out" r="20.246814360728305" stroke-width="0" stroke="#374151"></circle></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(757.1847045963179, 402.8013409019584)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">reviewer.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">reviewer.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">reviewer.rb</text></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(687.4299657134559, 856.9423846447222)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">CODE_OF_CONDU...</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">CODE_OF_CONDU...</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">CODE_OF_CONDU...</text></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(788.9846757350268, 859.3421087760426)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">.reviewer.exa...</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">.reviewer.exa...</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">.reviewer.exa...</text></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(726.4250919182904, 947.0721172937218)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">.reviewer.yml</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">.reviewer.yml</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">.reviewer.yml</text></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(726.687090398783, 755.9238323654778)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">Gemfile.lock</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">Gemfile.lock</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">Gemfile.lock</text></g><g style="fill:#CED6E0;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(656.2776843121794, 774.053081197875)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">reviewer.gemspec</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">reviewer.gemspec</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">reviewer.gemspec</text></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(646.3075304917123, 935.5086582680074)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">CHANGELOG.md</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">CHANGELOG.md</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">CHANGELOG.md</text></g><g style="fill:#6473F2;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(792.4478568898579, 778.7047877445898)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">README.md</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">README.md</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">README.md</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(355.4184691733666, 395.8977440745981)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">tool.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">tool.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">tool.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(453.66003516638904, 395.8977440745981)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">tool/settings.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">tool/settings.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">tool/settings.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(523.1975630378445, 335.21636724206417)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">command.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">command.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">command.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(176.26520220161186, 445.3500189745872)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">tools.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">tools.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">tools.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(605.0441527585806, 342.75082556501854)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">guidance.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">guidance.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">guidance.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(327.59590900349434, 569.4790692623358)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">history.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">history.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">history.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(534.3474887230652, 253.8625225793911)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">arguments.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">arguments.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">arguments.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(476.4643386600166, 578.911911443936)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">output.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">output.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">output.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(299.4858839094448, 207.73782607508076)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">runner.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">runner.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">runner.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(383.5814103897357, 501.6014766854548)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">result.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">result.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">result.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(370.84570420293034, 266.8449117959501)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">quiet.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">quiet.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">quiet.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(455.4320357843382, 266.8449117959501)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">verbose.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">verbose.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">verbose.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(265.3052220935813, 480.50667705487933)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">git/staged.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">git/staged.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">git/staged.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(643.5300677882587, 471.920566006636)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">verbosity.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">verbosity.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">verbosity.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(618.710163320952, 535.9504578797049)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">string.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">string.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">string.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(191.4503126965002, 309.1431465377067)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">keywords.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">keywords.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">keywords.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(281.17799339890166, 309.1431465377067)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">files.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">files.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">files.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(244.21679860063716, 373.9896454048579)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">tags.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">tags.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">tags.rb</text></g><g style="fill:#eb4d4b;transition:transform 0s ease-out, fill 0.1s ease-out" transform="translate(519.6457545955952, 464.8290172745834)"><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;transition:all 0.5s ease-out" fill="#4B5563" text-anchor="middle" dominant-baseline="middle" stroke="white" stroke-width="3" stroke-linejoin="round">verbosity.rb</text><text style="pointer-events:none;opacity:1;font-size:14px;font-weight:500;transition:all 0.5s ease-out" text-anchor="middle" dominant-baseline="middle">verbosity.rb</text><text style="pointer-events:none;opacity:0.9;font-size:14px;font-weight:500;mix-blend-mode:color-burn;transition:all 0.5s ease-out" fill="#110101" text-anchor="middle" dominant-baseline="middle">verbosity.rb</text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(458.1684758396736, 402.8013409019584)"><path fill="none" d="M 0 349.40190201003946 A 349.40190201003946 349.40190201003946 0 0 1 0 -349.40190201003946 A 349.40190201003946 349.40190201003946 0 0 1 0 349.40190201003946" id="CircleText--1" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--1" startOffset="50%">lib</textPath></text><path fill="none" d="M 0 349.40190201003946 A 349.40190201003946 349.40190201003946 0 0 1 0 -349.40190201003946 A 349.40190201003946 349.40190201003946 0 0 1 0 349.40190201003946" id="CircleText--2" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--2" startOffset="50%">lib</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(520.8364435594557, 806.4990877668961)"><path fill="none" d="M 0 33.11178860447648 A 33.11178860447648 33.11178860447648 0 0 1 0 -33.11178860447648 A 33.11178860447648 33.11178860447648 0 0 1 0 33.11178860447648" id="CircleText--3" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--3" startOffset="50%">.github/workf...</textPath></text><path fill="none" d="M 0 33.11178860447648 A 33.11178860447648 33.11178860447648 0 0 1 0 -33.11178860447648 A 33.11178860447648 33.11178860447648 0 0 1 0 33.11178860447648" id="CircleText--4" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--4" startOffset="50%">.github/workf...</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(409.6517236116371, 402.8013409019584)"><path fill="none" d="M 0 291.1473077312859 A 291.1473077312859 291.1473077312859 0 0 1 0 -291.1473077312859 A 291.1473077312859 291.1473077312859 0 0 1 0 291.1473077312859" id="CircleText--5" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--5" startOffset="50%">reviewer</textPath></text><path fill="none" d="M 0 291.1473077312859 A 291.1473077312859 291.1473077312859 0 0 1 0 -291.1473077312859 A 291.1473077312859 291.1473077312859 0 0 1 0 291.1473077312859" id="CircleText--6" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--6" startOffset="50%">reviewer</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(407.83945742807794, 501.6014766854548)"><path fill="none" d="M 0 62.26405035865341 A 62.26405035865341 62.26405035865341 0 0 1 0 -62.26405035865341 A 62.26405035865341 62.26405035865341 0 0 1 0 62.26405035865341" id="CircleText--7" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--7" startOffset="50%">shell</textPath></text><path fill="none" d="M 0 62.26405035865341 A 62.26405035865341 62.26405035865341 0 0 1 0 -62.26405035865341 A 62.26405035865341 62.26405035865341 0 0 1 0 62.26405035865341" id="CircleText--8" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--8" startOffset="50%">shell</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(408.44899912286195, 266.8449117959501)"><path fill="none" d="M 0 83.7994775020254 A 83.7994775020254 83.7994775020254 0 0 1 0 -83.7994775020254 A 83.7994775020254 83.7994775020254 0 0 1 0 83.7994775020254" id="CircleText--9" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--9" startOffset="50%">runner/strate...</textPath></text><path fill="none" d="M 0 83.7994775020254 A 83.7994775020254 83.7994775020254 0 0 1 0 -83.7994775020254 A 83.7994775020254 83.7994775020254 0 0 1 0 83.7994775020254" id="CircleText--10" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--10" startOffset="50%">runner/strate...</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(277.6542041828907, 480.50667705487933)"><path fill="none" d="M 0 59.19290440091251 A 59.19290440091251 59.19290440091251 0 0 1 0 -59.19290440091251 A 59.19290440091251 59.19290440091251 0 0 1 0 59.19290440091251" id="CircleText--11" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--11" startOffset="50%">keywords</textPath></text><path fill="none" d="M 0 59.19290440091251 A 59.19290440091251 59.19290440091251 0 0 1 0 -59.19290440091251 A 59.19290440091251 59.19290440091251 0 0 1 0 59.19290440091251" id="CircleText--12" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--12" startOffset="50%">keywords</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(578.9817228671643, 482.6836693665573)"><path fill="none" d="M 0 99.49432161596253 A 99.49432161596253 99.49432161596253 0 0 1 0 -99.49432161596253 A 99.49432161596253 99.49432161596253 0 0 1 0 99.49432161596253" id="CircleText--13" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--13" startOffset="50%">command</textPath></text><path fill="none" d="M 0 99.49432161596253 A 99.49432161596253 99.49432161596253 0 0 1 0 -99.49432161596253 A 99.49432161596253 99.49432161596253 0 0 1 0 99.49432161596253" id="CircleText--14" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--14" startOffset="50%">command</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(231.7281199383259, 318.8649338109235)"><path fill="none" d="M 0 89.99244862172178 A 89.99244862172178 89.99244862172178 0 0 1 0 -89.99244862172178 A 89.99244862172178 89.99244862172178 0 0 1 0 89.99244862172178" id="CircleText--15" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--15" startOffset="50%">arguments</textPath></text><path fill="none" d="M 0 89.99244862172178 A 89.99244862172178 89.99244862172178 0 0 1 0 -89.99244862172178 A 89.99244862172178 89.99244862172178 0 0 1 0 89.99244862172178" id="CircleText--16" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--16" startOffset="50%">arguments</textPath></text></g><g style="pointer-events:none;transition:all 0.5s ease-out" transform="translate(544.5152135162864, 471.920566006636)"><path fill="none" d="M 0 58.960071361511915 A 58.960071361511915 58.960071361511915 0 0 1 0 -58.960071361511915 A 58.960071361511915 58.960071361511915 0 0 1 0 58.960071361511915" id="CircleText--17" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151" stroke="white" stroke-width="6"><textPath href="#CircleText--17" startOffset="50%">string</textPath></text><path fill="none" d="M 0 58.960071361511915 A 58.960071361511915 58.960071361511915 0 0 1 0 -58.960071361511915 A 58.960071361511915 58.960071361511915 0 0 1 0 58.960071361511915" id="CircleText--18" transform="rotate(0)" style="pointer-events:none"></path><text text-anchor="middle" style="font-size:14px;transition:all 0.5s ease-out" fill="#374151"><textPath href="#CircleText--18" startOffset="50%">string</textPath></text></g><g transform="translate(920, 935)"><g transform="translate(0, 0)"><circle r="5" fill="#6473F2"></circle><text x="10" style="font-size:14px;font-weight:300" dominant-baseline="middle">.md</text></g><g transform="translate(0, 15)"><circle r="5" fill="#eb4d4b"></circle><text x="10" style="font-size:14px;font-weight:300" dominant-baseline="middle">.rb</text></g><g transform="translate(0, 30)"><circle r="5" fill="#FFC312"></circle><text x="10" style="font-size:14px;font-weight:300" dominant-baseline="middle">.svg</text></g><div class="w-20 whitespace-nowrap text-sm text-gray-500 font-light italic">each dot sized by file size</div></g></svg>