reviewer 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.alexignore +1 -0
- data/.github/workflows/main.yml +5 -3
- data/.reviewer.example.yml +20 -10
- data/.reviewer.future.yml +221 -0
- data/.reviewer.yml +45 -8
- data/.reviewer_stdout +0 -0
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +29 -28
- data/LICENSE.txt +4 -20
- data/README.md +26 -7
- data/lib/reviewer/arguments/files.rb +14 -8
- data/lib/reviewer/arguments/keywords.rb +5 -2
- data/lib/reviewer/arguments/tags.rb +11 -4
- data/lib/reviewer/arguments.rb +11 -4
- data/lib/reviewer/batch.rb +41 -14
- data/lib/reviewer/command/string/env.rb +4 -0
- data/lib/reviewer/command/string/flags.rb +12 -1
- data/lib/reviewer/command/string.rb +12 -18
- data/lib/reviewer/command.rb +7 -32
- data/lib/reviewer/configuration.rb +8 -1
- data/lib/reviewer/conversions.rb +0 -11
- data/lib/reviewer/guidance.rb +9 -5
- data/lib/reviewer/history.rb +32 -1
- data/lib/reviewer/keywords/git/staged.rb +16 -0
- data/lib/reviewer/output/printer.rb +44 -0
- data/lib/reviewer/output/scrubber.rb +48 -0
- data/lib/reviewer/output/token.rb +85 -0
- data/lib/reviewer/output.rb +73 -43
- data/lib/reviewer/runner/strategies/captured.rb +157 -0
- data/lib/reviewer/runner/strategies/{verbose.rb → passthrough.rb} +13 -13
- data/lib/reviewer/runner.rb +71 -13
- data/lib/reviewer/shell/result.rb +22 -7
- data/lib/reviewer/shell/timer.rb +15 -0
- data/lib/reviewer/shell.rb +7 -11
- data/lib/reviewer/tool/settings.rb +12 -5
- data/lib/reviewer/tool.rb +25 -3
- data/lib/reviewer/version.rb +1 -1
- data/lib/reviewer.rb +11 -10
- data/reviewer.gemspec +9 -5
- data/structure.svg +1 -0
- metadata +34 -28
- data/.ruby-version +0 -1
- data/lib/reviewer/command/string/verbosity.rb +0 -51
- data/lib/reviewer/command/verbosity.rb +0 -65
- data/lib/reviewer/printer.rb +0 -25
- 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
|
-
# @
|
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
|
-
|
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
|
40
|
-
exit_status
|
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
|
-
|
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
|
data/lib/reviewer/shell/timer.rb
CHANGED
@@ -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
|
data/lib/reviewer/shell.rb
CHANGED
@@ -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
|
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
|
-
|
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(
|
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 [
|
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
|
data/lib/reviewer/version.rb
CHANGED
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
|
-
#
|
37
|
-
# @param
|
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
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
113
|
+
output.clear if clear_screen
|
113
114
|
|
114
|
-
results = Batch.
|
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['
|
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 '
|
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-
|
41
|
-
spec.add_development_dependency 'psych'
|
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>
|