moult 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +44 -0
  3. data/LICENSE.txt +201 -0
  4. data/NOTICE +4 -0
  5. data/README.md +331 -0
  6. data/exe/moult +6 -0
  7. data/lib/moult/abc.rb +133 -0
  8. data/lib/moult/boundaries/packwerk.rb +114 -0
  9. data/lib/moult/boundaries/severity.rb +87 -0
  10. data/lib/moult/boundaries.rb +77 -0
  11. data/lib/moult/boundaries_report.rb +106 -0
  12. data/lib/moult/churn.rb +52 -0
  13. data/lib/moult/cli/boundaries_command.rb +83 -0
  14. data/lib/moult/cli/coverage_command.rb +101 -0
  15. data/lib/moult/cli/dead_code_command.rb +112 -0
  16. data/lib/moult/cli/duplication_command.rb +92 -0
  17. data/lib/moult/cli/flags_command.rb +95 -0
  18. data/lib/moult/cli/gate_command.rb +113 -0
  19. data/lib/moult/cli/health_command.rb +117 -0
  20. data/lib/moult/cli/hotspots_command.rb +104 -0
  21. data/lib/moult/cli.rb +102 -0
  22. data/lib/moult/clones.rb +91 -0
  23. data/lib/moult/cloud_upload.rb +29 -0
  24. data/lib/moult/confidence/rules.rb +128 -0
  25. data/lib/moult/confidence.rb +106 -0
  26. data/lib/moult/coverage/resolver.rb +56 -0
  27. data/lib/moult/coverage.rb +176 -0
  28. data/lib/moult/coverage_report.rb +98 -0
  29. data/lib/moult/dead_code.rb +119 -0
  30. data/lib/moult/dead_code_report.rb +65 -0
  31. data/lib/moult/diff.rb +177 -0
  32. data/lib/moult/discovery.rb +38 -0
  33. data/lib/moult/duplication/confidence.rb +92 -0
  34. data/lib/moult/duplication.rb +112 -0
  35. data/lib/moult/duplication_report.rb +89 -0
  36. data/lib/moult/flag_scanner.rb +150 -0
  37. data/lib/moult/flags/classification.rb +79 -0
  38. data/lib/moult/flags/snapshot.rb +162 -0
  39. data/lib/moult/flags/staleness.rb +145 -0
  40. data/lib/moult/flags.rb +131 -0
  41. data/lib/moult/flags_report.rb +136 -0
  42. data/lib/moult/formatters/boundaries_json.rb +20 -0
  43. data/lib/moult/formatters/boundaries_table.rb +53 -0
  44. data/lib/moult/formatters/coverage_json.rb +19 -0
  45. data/lib/moult/formatters/coverage_table.rb +60 -0
  46. data/lib/moult/formatters/dead_code_json.rb +20 -0
  47. data/lib/moult/formatters/dead_code_table.rb +66 -0
  48. data/lib/moult/formatters/duplication_json.rb +20 -0
  49. data/lib/moult/formatters/duplication_table.rb +55 -0
  50. data/lib/moult/formatters/flags_json.rb +20 -0
  51. data/lib/moult/formatters/flags_table.rb +76 -0
  52. data/lib/moult/formatters/gate_github.rb +52 -0
  53. data/lib/moult/formatters/gate_json.rb +20 -0
  54. data/lib/moult/formatters/gate_message.rb +19 -0
  55. data/lib/moult/formatters/gate_sarif.rb +78 -0
  56. data/lib/moult/formatters/gate_table.rb +71 -0
  57. data/lib/moult/formatters/health_json.rb +20 -0
  58. data/lib/moult/formatters/health_table.rb +80 -0
  59. data/lib/moult/formatters/json.rb +23 -0
  60. data/lib/moult/formatters/table.rb +70 -0
  61. data/lib/moult/formatters/text_table.rb +39 -0
  62. data/lib/moult/gate/config.rb +55 -0
  63. data/lib/moult/gate/evaluation.rb +172 -0
  64. data/lib/moult/gate/policy.rb +103 -0
  65. data/lib/moult/gate.rb +199 -0
  66. data/lib/moult/gate_report.rb +97 -0
  67. data/lib/moult/git.rb +83 -0
  68. data/lib/moult/health/score.rb +291 -0
  69. data/lib/moult/health.rb +320 -0
  70. data/lib/moult/health_report.rb +97 -0
  71. data/lib/moult/index.rb +228 -0
  72. data/lib/moult/parser.rb +101 -0
  73. data/lib/moult/rails_conventions.rb +124 -0
  74. data/lib/moult/report.rb +114 -0
  75. data/lib/moult/scoring.rb +82 -0
  76. data/lib/moult/span.rb +17 -0
  77. data/lib/moult/symbol_id.rb +30 -0
  78. data/lib/moult/symbol_scanner.rb +100 -0
  79. data/lib/moult/version.rb +5 -0
  80. data/lib/moult.rb +84 -0
  81. data/schema/boundaries.schema.json +125 -0
  82. data/schema/common.schema.json +76 -0
  83. data/schema/coverage.schema.json +83 -0
  84. data/schema/deadcode.schema.json +106 -0
  85. data/schema/duplication.schema.json +128 -0
  86. data/schema/flags.schema.json +157 -0
  87. data/schema/gate.schema.json +165 -0
  88. data/schema/health.schema.json +157 -0
  89. data/schema/hotspots.schema.json +106 -0
  90. metadata +185 -0
@@ -0,0 +1,157 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/moult-rb/moult-rb/blob/main/schema/health.schema.json",
4
+ "title": "Moult health report",
5
+ "description": "Typed output contract for `moult health`. One of Moult's two protected APIs. The composite is a confidence-graded health SIGNAL aggregated from the other analyses, never a verdict: it carries its contributing components and their reasons so the number is auditable, and it never asserts a pass/fail. The components list is open: future analyses (boundaries, flags) plug in as additional entries without a schema bump.",
6
+ "type": "object",
7
+ "required": ["schema_version", "tool", "analysis", "overall", "components", "files"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": {
11
+ "description": "Bumped only on a breaking change to this shape.",
12
+ "type": "integer",
13
+ "const": 1
14
+ },
15
+ "tool": {
16
+ "type": "object",
17
+ "required": ["name", "version"],
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "name": {"type": "string"},
21
+ "version": {"type": "string"}
22
+ }
23
+ },
24
+ "analysis": {
25
+ "type": "object",
26
+ "required": ["root", "git_ref", "generated_at", "coverage", "churn"],
27
+ "additionalProperties": false,
28
+ "properties": {
29
+ "root": {"type": "string"},
30
+ "git_ref": {"type": ["string", "null"]},
31
+ "generated_at": {"type": ["string", "null"], "format": "date-time"},
32
+ "coverage": {"$ref": "common.schema.json#/$defs/coverage_source"},
33
+ "churn": {
34
+ "type": "object",
35
+ "required": ["window", "since"],
36
+ "additionalProperties": false,
37
+ "properties": {
38
+ "window": {"description": "Human description of the churn window fed to the complexity component.", "type": ["string", "null"]},
39
+ "since": {"description": "Resolved --since boundary, when an explicit one was given.", "type": ["string", "null"]}
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "overall": {
45
+ "description": "The composite health signal. score/grade are null only when no component ran.",
46
+ "type": "object",
47
+ "required": ["score", "grade", "components_present", "components_total", "files_total"],
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "score": {"$ref": "#/$defs/nullable_unit_interval"},
51
+ "grade": {"$ref": "#/$defs/nullable_grade"},
52
+ "components_present": {"description": "Components that actually contributed to the composite.", "type": "integer", "minimum": 0},
53
+ "components_total": {"description": "Components considered (present + skipped + errored).", "type": "integer", "minimum": 0},
54
+ "files_total": {"description": "Signal-bearing files; files[] may be display-limited but this is the full count.", "type": "integer", "minimum": 0}
55
+ }
56
+ },
57
+ "components": {
58
+ "description": "One entry per considered analysis. Absent analyses still appear (present=false) so the record of what ran is honest. Open-ended: new analyses add entries without a schema bump.",
59
+ "type": "array",
60
+ "items": {"$ref": "#/$defs/component"}
61
+ },
62
+ "files": {
63
+ "description": "Per-file roll-up, the cross-analysis join surface. Each file carries its contributing symbol_ids so findings join to the hotspots/deadcode/duplication/coverage contracts.",
64
+ "type": "array",
65
+ "items": {"$ref": "#/$defs/file"}
66
+ }
67
+ },
68
+ "$defs": {
69
+ "nullable_unit_interval": {
70
+ "description": "A health score in [0, 1] (1 = healthy), or null where not asserted. A graded signal, never a verdict.",
71
+ "oneOf": [
72
+ {"type": "null"},
73
+ {"$ref": "common.schema.json#/$defs/unit_interval"}
74
+ ]
75
+ },
76
+ "grade": {
77
+ "description": "Letter grade bucketed from a health score. A coarse reading of the same signal, never a pass/fail gate.",
78
+ "type": "string",
79
+ "enum": ["A", "B", "C", "D", "F"]
80
+ },
81
+ "nullable_grade": {
82
+ "oneOf": [
83
+ {"type": "null"},
84
+ {"$ref": "#/$defs/grade"}
85
+ ]
86
+ },
87
+ "reason": {
88
+ "description": "One auditable contribution to a component's sub-score. `value` is the observed [0, 1] quantity (a ratio/sub-score), not a signed delta - health sub-scores are ratios, not delta-sums.",
89
+ "type": "object",
90
+ "required": ["rule", "value", "detail"],
91
+ "additionalProperties": false,
92
+ "properties": {
93
+ "rule": {"type": "string"},
94
+ "value": {"$ref": "common.schema.json#/$defs/unit_interval"},
95
+ "detail": {"type": "string"}
96
+ }
97
+ },
98
+ "component": {
99
+ "description": "One graded component of the composite. Carries its category, its static weight, its renormalized share among present components, an auditable stats summary, and its reasons. Never asserts certainty.",
100
+ "type": "object",
101
+ "required": ["name", "category", "present", "score", "weight", "normalized_weight", "summary", "reasons", "diagnostic"],
102
+ "additionalProperties": false,
103
+ "properties": {
104
+ "name": {"description": "Stable component slot key, e.g. \"complexity\", \"dead_code\", \"duplication\", \"coverage\".", "type": "string"},
105
+ "category": {"$ref": "common.schema.json#/$defs/category"},
106
+ "present": {"description": "Whether this analysis contributed to the composite.", "type": "boolean"},
107
+ "score": {
108
+ "description": "Health sub-score in [0, 1] (1 = healthy); null when the component is absent.",
109
+ "$ref": "#/$defs/nullable_unit_interval"
110
+ },
111
+ "weight": {
112
+ "description": "Static, pinned weight of this component before renormalization.",
113
+ "$ref": "common.schema.json#/$defs/unit_interval"
114
+ },
115
+ "normalized_weight": {
116
+ "description": "Share of the composite this component carried, renormalized over present components; null when absent.",
117
+ "$ref": "#/$defs/nullable_unit_interval"
118
+ },
119
+ "summary": {
120
+ "description": "Small free-form stats hash backing the sub-score (counts/ratios). Auditable, not a strict surface; {} when absent.",
121
+ "type": "object"
122
+ },
123
+ "reasons": {
124
+ "description": "The observations behind the sub-score, in application order.",
125
+ "type": "array",
126
+ "items": {"$ref": "#/$defs/reason"}
127
+ },
128
+ "diagnostic": {
129
+ "description": "Why a component was skipped or errored; null when it contributed normally.",
130
+ "type": ["string", "null"]
131
+ }
132
+ }
133
+ },
134
+ "file": {
135
+ "description": "One file's rolled-up health. Joins to the other analyses via the symbol_ids it lists.",
136
+ "type": "object",
137
+ "required": ["path", "score", "grade", "components", "symbol_ids", "symbol_count"],
138
+ "additionalProperties": false,
139
+ "properties": {
140
+ "path": {"type": "string"},
141
+ "score": {"$ref": "common.schema.json#/$defs/unit_interval"},
142
+ "grade": {"$ref": "#/$defs/grade"},
143
+ "components": {
144
+ "description": "Per-component sub-scores for this file, present components only. Open-ended map keyed by component name.",
145
+ "type": "object",
146
+ "additionalProperties": {"$ref": "common.schema.json#/$defs/unit_interval"}
147
+ },
148
+ "symbol_ids": {
149
+ "description": "Contributing join keys (\"<path>:<start_line>:<fqname>\"), shared with the other contracts. Capped for payload size; symbol_count records the true total.",
150
+ "type": "array",
151
+ "items": {"type": "string"}
152
+ },
153
+ "symbol_count": {"description": "Total contributing symbols before the symbol_ids cap.", "type": "integer", "minimum": 0}
154
+ }
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,106 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/moult-rb/moult-rb/blob/main/schema/hotspots.schema.json",
4
+ "title": "Moult hotspots report",
5
+ "description": "Typed output contract for `moult hotspots`. One of Moult's two protected APIs.",
6
+ "type": "object",
7
+ "required": ["schema_version", "tool", "analysis", "hotspots"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": {
11
+ "description": "Bumped only on a breaking change to this shape.",
12
+ "type": "integer",
13
+ "const": 1
14
+ },
15
+ "tool": {
16
+ "type": "object",
17
+ "required": ["name", "version"],
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "name": {"type": "string"},
21
+ "version": {"type": "string"}
22
+ }
23
+ },
24
+ "analysis": {
25
+ "type": "object",
26
+ "required": ["root", "git_ref", "generated_at", "churn"],
27
+ "additionalProperties": false,
28
+ "properties": {
29
+ "root": {"type": "string"},
30
+ "git_ref": {"type": ["string", "null"]},
31
+ "generated_at": {"type": ["string", "null"], "format": "date-time"},
32
+ "churn": {
33
+ "type": "object",
34
+ "required": ["window", "since"],
35
+ "additionalProperties": false,
36
+ "properties": {
37
+ "window": {"type": ["string", "null"]},
38
+ "since": {"type": ["string", "null"]}
39
+ }
40
+ }
41
+ }
42
+ },
43
+ "hotspots": {
44
+ "type": "array",
45
+ "items": {"$ref": "#/$defs/hotspot"}
46
+ }
47
+ },
48
+ "$defs": {
49
+ "method": {
50
+ "type": "object",
51
+ "required": ["symbol_id", "name", "span", "abc", "confidence", "category"],
52
+ "additionalProperties": false,
53
+ "properties": {
54
+ "symbol_id": {
55
+ "description": "Stable join key for the Phase 3 coverage merge: \"<path>:<start_line>:<fqname>\".",
56
+ "type": "string"
57
+ },
58
+ "name": {
59
+ "description": "Lexical fully-qualified name (Class#method or Class.method).",
60
+ "type": "string"
61
+ },
62
+ "span": {"$ref": "common.schema.json#/$defs/span"},
63
+ "abc": {
64
+ "description": "Flog-style weighted ABC complexity score.",
65
+ "type": "number",
66
+ "minimum": 0
67
+ },
68
+ "confidence": {"$ref": "common.schema.json#/$defs/confidence"},
69
+ "category": {"$ref": "common.schema.json#/$defs/category"}
70
+ }
71
+ },
72
+ "hotspot": {
73
+ "type": "object",
74
+ "required": ["path", "score", "complexity", "churn", "methods", "confidence", "category"],
75
+ "additionalProperties": false,
76
+ "properties": {
77
+ "path": {
78
+ "description": "Path relative to the analysis root.",
79
+ "type": "string"
80
+ },
81
+ "score": {
82
+ "description": "Ranking score: complexity x churn.",
83
+ "type": "number",
84
+ "minimum": 0
85
+ },
86
+ "complexity": {
87
+ "description": "Aggregate ABC complexity for the file.",
88
+ "type": "number",
89
+ "minimum": 0
90
+ },
91
+ "churn": {
92
+ "description": "Commits touching the file within the churn window.",
93
+ "type": "integer",
94
+ "minimum": 0
95
+ },
96
+ "methods": {
97
+ "description": "Worst methods in the file, highest ABC first.",
98
+ "type": "array",
99
+ "items": {"$ref": "#/$defs/method"}
100
+ },
101
+ "confidence": {"$ref": "common.schema.json#/$defs/confidence"},
102
+ "category": {"$ref": "common.schema.json#/$defs/category"}
103
+ }
104
+ }
105
+ }
106
+ }
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moult
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - The Moult authors
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2026-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prism
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.24'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0.24'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubydex
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: flay
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ description: Moult sheds dead code. `moult hotspots` ranks files by a complexity x
56
+ churn score (Prism-parsed ABC complexity per method x per-file git churn); `moult
57
+ deadcode` lists confidence-graded unused-method and unused-constant candidates over
58
+ a rubydex definition graph, with Rails entrypoint awareness. Every finding carries
59
+ a confidence and its reasons, never a claim of certain death.
60
+ email:
61
+ - contact@moult.dev
62
+ executables:
63
+ - moult
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - CHANGELOG.md
68
+ - LICENSE.txt
69
+ - NOTICE
70
+ - README.md
71
+ - exe/moult
72
+ - lib/moult.rb
73
+ - lib/moult/abc.rb
74
+ - lib/moult/boundaries.rb
75
+ - lib/moult/boundaries/packwerk.rb
76
+ - lib/moult/boundaries/severity.rb
77
+ - lib/moult/boundaries_report.rb
78
+ - lib/moult/churn.rb
79
+ - lib/moult/cli.rb
80
+ - lib/moult/cli/boundaries_command.rb
81
+ - lib/moult/cli/coverage_command.rb
82
+ - lib/moult/cli/dead_code_command.rb
83
+ - lib/moult/cli/duplication_command.rb
84
+ - lib/moult/cli/flags_command.rb
85
+ - lib/moult/cli/gate_command.rb
86
+ - lib/moult/cli/health_command.rb
87
+ - lib/moult/cli/hotspots_command.rb
88
+ - lib/moult/clones.rb
89
+ - lib/moult/cloud_upload.rb
90
+ - lib/moult/confidence.rb
91
+ - lib/moult/confidence/rules.rb
92
+ - lib/moult/coverage.rb
93
+ - lib/moult/coverage/resolver.rb
94
+ - lib/moult/coverage_report.rb
95
+ - lib/moult/dead_code.rb
96
+ - lib/moult/dead_code_report.rb
97
+ - lib/moult/diff.rb
98
+ - lib/moult/discovery.rb
99
+ - lib/moult/duplication.rb
100
+ - lib/moult/duplication/confidence.rb
101
+ - lib/moult/duplication_report.rb
102
+ - lib/moult/flag_scanner.rb
103
+ - lib/moult/flags.rb
104
+ - lib/moult/flags/classification.rb
105
+ - lib/moult/flags/snapshot.rb
106
+ - lib/moult/flags/staleness.rb
107
+ - lib/moult/flags_report.rb
108
+ - lib/moult/formatters/boundaries_json.rb
109
+ - lib/moult/formatters/boundaries_table.rb
110
+ - lib/moult/formatters/coverage_json.rb
111
+ - lib/moult/formatters/coverage_table.rb
112
+ - lib/moult/formatters/dead_code_json.rb
113
+ - lib/moult/formatters/dead_code_table.rb
114
+ - lib/moult/formatters/duplication_json.rb
115
+ - lib/moult/formatters/duplication_table.rb
116
+ - lib/moult/formatters/flags_json.rb
117
+ - lib/moult/formatters/flags_table.rb
118
+ - lib/moult/formatters/gate_github.rb
119
+ - lib/moult/formatters/gate_json.rb
120
+ - lib/moult/formatters/gate_message.rb
121
+ - lib/moult/formatters/gate_sarif.rb
122
+ - lib/moult/formatters/gate_table.rb
123
+ - lib/moult/formatters/health_json.rb
124
+ - lib/moult/formatters/health_table.rb
125
+ - lib/moult/formatters/json.rb
126
+ - lib/moult/formatters/table.rb
127
+ - lib/moult/formatters/text_table.rb
128
+ - lib/moult/gate.rb
129
+ - lib/moult/gate/config.rb
130
+ - lib/moult/gate/evaluation.rb
131
+ - lib/moult/gate/policy.rb
132
+ - lib/moult/gate_report.rb
133
+ - lib/moult/git.rb
134
+ - lib/moult/health.rb
135
+ - lib/moult/health/score.rb
136
+ - lib/moult/health_report.rb
137
+ - lib/moult/index.rb
138
+ - lib/moult/parser.rb
139
+ - lib/moult/rails_conventions.rb
140
+ - lib/moult/report.rb
141
+ - lib/moult/scoring.rb
142
+ - lib/moult/span.rb
143
+ - lib/moult/symbol_id.rb
144
+ - lib/moult/symbol_scanner.rb
145
+ - lib/moult/version.rb
146
+ - schema/boundaries.schema.json
147
+ - schema/common.schema.json
148
+ - schema/coverage.schema.json
149
+ - schema/deadcode.schema.json
150
+ - schema/duplication.schema.json
151
+ - schema/flags.schema.json
152
+ - schema/gate.schema.json
153
+ - schema/health.schema.json
154
+ - schema/hotspots.schema.json
155
+ homepage: https://github.com/moult-rb/moult-rb
156
+ licenses:
157
+ - Apache-2.0
158
+ metadata:
159
+ homepage_uri: https://github.com/moult-rb/moult-rb
160
+ source_code_uri: https://github.com/moult-rb/moult-rb
161
+ changelog_uri: https://github.com/moult-rb/moult-rb/blob/main/CHANGELOG.md
162
+ bug_tracker_uri: https://github.com/moult-rb/moult-rb/issues
163
+ documentation_uri: https://github.com/moult-rb/moult-rb#readme
164
+ rubygems_mfa_required: 'true'
165
+ allowed_push_host: https://rubygems.org
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '3.3'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubygems_version: 3.5.22
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Confidence-graded codebase intelligence for Ruby and Rails.
185
+ test_files: []