crap4ruby 0.1.1 → 0.2.1

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.
data/scoring-audit.md ADDED
@@ -0,0 +1,251 @@
1
+ # Scoring correctness audit
2
+
3
+ Audited 2026-10-28 at commit `0f88ceef5a6e9530487428392e9d698635a1b37f`.
4
+
5
+ ## Follow-up implementation
6
+
7
+ The working tree now implements the selected O1 and O6 policies. The original findings below describe the audited commit, before these changes.
8
+
9
+ 1. F1: Fixed heredoc descendant ranges, including exclusion of nested method heredocs from enclosing coverage.
10
+ 2. F2: Shared declaration lines and body lines with trailing code after the definition now produce unknown coverage. Unknown scores pass a threshold only when `CC^2 + CC` fits it. Otherwise, the check exits 1; measured violations retain exit 2.
11
+ 3. F3: Coverage fractions, scores, and decimal threshold comparisons retain exact rational arithmetic. Display rounding does not affect the result.
12
+ 4. F4: Explicit definitions inside parameter defaults and superclass expressions are discovered.
13
+ 5. F5: Complexity follows RuboCop 1.92.1, and literal bare `define_method` blocks are discovered. The remaining documented limits, including line coverage, runtime metaprogramming, and `.rb` source selection, still apply.
14
+
15
+ The complete repository gate passes on CRuby 3.3.11 and 4.0.9: 54 tests, 260 assertions, full static call typing, and all library CRAP scores at or below 10. An independent comparison matched 649 method results against the actual RuboCop 1.92.1 CLI. Eighteen additional deliberate scoring and output mutations were caught by regression assertions.
16
+
17
+ Independent CLI QA found and verified repairs for implicit block parameter locations, trailing-line coverage contamination, control characters in method names, and misleading rounded threshold diagnostics. The final tested source hashes match the working tree. Ruby 3.4 remains untested in this session.
18
+
19
+ These public scoring and threshold changes require a minor release. No version change or commit was made. The result remains CRAP with a documented line-coverage proxy, not original basis path measurement or an exhaustive runtime Ruby inventory.
20
+
21
+ ## Result
22
+
23
+ The algebra matches the CRAP formula. The implementation cannot claim complete Ruby coverage or universally correct scores.
24
+
25
+ This audit reproduced incorrect coverage attribution, omitted explicit definitions, and a false threshold failure. Some broader limits are already documented design choices.
26
+
27
+ The relevant distinction is between formula correctness, input measurement, and source selection. Correct algebra does not correct missing methods or inaccurate coverage.
28
+
29
+ ## Reproduced findings
30
+
31
+ ### F1: Final heredocs can lose executable coverage lines
32
+
33
+ Severity: high. This is an implementation defect in method-body line selection.
34
+
35
+ [Analyzer#body_lines](lib/crap4ruby/analyzer.rb#L118) uses the outer node's location range. A final heredoc's outer location can end at its introducer.
36
+
37
+ The interpolation contains executable descendants outside that range:
38
+
39
+ ```ruby
40
+ class Sample
41
+ def sample(flag)
42
+ <<~TEXT
43
+ #{if flag
44
+ :yes
45
+ else
46
+ :no
47
+ end}
48
+ TEXT
49
+ end
50
+ end
51
+ ```
52
+
53
+ After `Sample.new.sample(true)`, fresh SimpleCov data reports executable lines 4, 5, and 7 with hits `1, 1, 0`.
54
+
55
+ The analyzer selects only line 3, whose hit count is `nil`. Reported complexity is 2, but coverage and CRAP are N/A.
56
+
57
+ With the documented line-coverage policy, coverage should be `2/3` and CRAP should be approximately `2.148148`.
58
+
59
+ The real CLI exits 0 with `--threshold 1`, because [threshold_status](lib/crap4ruby/cli.rb#L111) ignores unknown scores.
60
+
61
+ Correction: include executable heredoc descendants when selecting body locations. Preserve exclusions for nested definitions. Add a real SimpleCov regression fixture.
62
+
63
+ ### F2: Uncalled inline and endless methods can receive full coverage
64
+
65
+ Severity: high for score reliability. This is a documented measurement limitation with a demonstrated false pass.
66
+
67
+ ```ruby
68
+ class Sample
69
+ def sample(flag) = flag ? :yes : :no
70
+ end
71
+ ```
72
+
73
+ Loading this file without calling `sample` gives its definition line a positive hit count.
74
+
75
+ [Coverage#fraction](lib/crap4ruby/coverage.rb#L40) interprets that line as covered method code. The report shows CC 2, coverage 100%, and CRAP 2.
76
+
77
+ The uncalled method should have coverage 0% and CRAP 6. The CLI exits 0 with `--threshold 3`.
78
+
79
+ The same issue affects `def sample; :yes; end`. Distinct methods or expressions sharing a line also cannot be separated reliably.
80
+
81
+ The [README limitation](README.md#L170) acknowledges shared lines. Documentation does not make the resulting 100% value proof of method execution.
82
+
83
+ Correction: require independent invocation evidence for ambiguous definition lines, or report their coverage as unknown. Define how unknown scores affect threshold enforcement.
84
+
85
+ ### F3: Floating-point error can fail a mathematically equal threshold
86
+
87
+ Severity: medium. This is a numeric boundary defect.
88
+
89
+ With CC 2 and three covered lines out of five:
90
+
91
+ ```text
92
+ Exact CRAP = 2^2 * (1 - 3/5)^3 + 2 = 2.256
93
+ Computed Float = 2.2560000000000002
94
+ Threshold = 2.256
95
+ CLI exit = 2
96
+ Snapshot CRAP = 2.256
97
+ ```
98
+
99
+ This was reproduced through the real CLI using fresh SimpleCov data from this method, called with `true`:
100
+
101
+ ```ruby
102
+ def sample(flag)
103
+ value = 1
104
+ if flag
105
+ value + 1
106
+ else
107
+ value - 1
108
+ value - 2
109
+ end
110
+ end
111
+ ```
112
+
113
+ [Coverage#fraction](lib/crap4ruby/coverage.rb#L50) converts the ratio to Float. [Score.call](lib/crap4ruby/score.rb#L14) propagates rounding, and [threshold_status](lib/crap4ruby/cli.rb#L112) compares it strictly.
114
+
115
+ Correction: define exact decimal threshold semantics and preserve sufficient numeric precision through comparison. Do not compare rounded display values.
116
+
117
+ ### F4: Some explicit method definitions are omitted
118
+
119
+ Severity: medium. This contradicts the stated coverage of explicit and nested definitions.
120
+
121
+ ```ruby
122
+ def outer(value = (def inner(flag)
123
+ flag ? :yes : :no
124
+ end))
125
+ value
126
+ end
127
+ ```
128
+
129
+ Ruby installs `inner` when the default expression executes. The analyzer returns only `outer`, so `inner` never receives a score.
130
+
131
+ [Analyzer#discover_method](lib/crap4ruby/analyzer.rb#L64) discovers nested definitions only in the body. It does not traverse parameter expressions for definitions.
132
+
133
+ The complexity counter does inspect parameters, but it deliberately stops at nested definitions. Therefore, the omitted method's decisions are not counted elsewhere.
134
+
135
+ A second parsed example, `class Sample < (def outer; true; end; Object); end`, returns no methods.
136
+
137
+ [Analyzer#discover](lib/crap4ruby/analyzer.rb#L38) visits a class body without visiting its superclass expression.
138
+
139
+ Correction: separate definition discovery from complexity ownership. Visit executable parameter and superclass expressions while preserving each nested method's independent score.
140
+
141
+ ### F5: The metric has explicit scope and policy gaps
142
+
143
+ Severity: a contract limitation, not one isolated implementation defect.
144
+
145
+ | Area | Observed behavior | Consequence |
146
+ | --- | --- | --- |
147
+ | Iteration | `items.each { ... }` adds no point; equivalent `for` adds one. | Ruby spelling changes the score. |
148
+ | Safe navigation | Every operation adds one, including repeated operations on the same local variable. | Differs from RuboCop's repeated-receiver discount. |
149
+ | Parameter defaults | Explicit decisions count toward CC; default-expression lines do not enter coverage. | Untested defaults can accompany reported 100% coverage. |
150
+ | Method creation | Literal `define_method`, aliases, and generated accessors are excluded. | The report does not enumerate all runtime methods. |
151
+ | Dynamic ownership | Dynamic receivers and some namespace expressions are skipped. `Class.new { def sample; ...; end }` is attributed lexically to `Object`. | Ownership is not a runtime method inventory. |
152
+ | Source selection | Only `.rb` files survive [Discovery.call](lib/crap4ruby/discovery.rb#L34), even when another filename is explicit. | `.rake`, `.gemspec`, `Rakefile`, `Gemfile`, `config.ru`, and extensionless scripts are excluded. |
153
+ | Non-method code | Top-level and class/module initialization decisions receive no independent score. | Whole-program Ruby coverage is outside the metric's scope. |
154
+ | Coverage freshness | Supplied suites merge without an age cutoff or source-content identity check. | Old results can describe different source text. |
155
+ | Coverage granularity | Positive line hits define coverage; branch records are ignored. | Untested branches on executed lines can appear fully covered. |
156
+
157
+ These policies are mostly documented in the [complexity rules and limits](README.md#L116). They prevent an unrestricted claim about every Ruby construct.
158
+
159
+ Additional probes found CC 1 for a standalone `value in [Integer]` predicate and no extra point for a pattern alternative or flip-flop.
160
+
161
+ Those constructs need explicit policy decisions before calling their counts wrong. Neither the CRAP formula nor the cited ports supplies a complete Ruby specification.
162
+
163
+ ## What passed
164
+
165
+ The [scoring expression](lib/crap4ruby/score.rb#L14) matches:
166
+
167
+ ```text
168
+ CRAP = CC^2 * (1 - coverage_fraction)^3 + CC
169
+ ```
170
+
171
+ At zero coverage it produces `CC^2 + CC`. At full coverage it produces `CC`. Percentage conversion happens after calculation.
172
+
173
+ The existing suite passed: `bundle exec rake test`, 33 tests, zero failures.
174
+
175
+ A separate 49-case parser matrix matched the README's documented counts. It covered conditionals, loops, cases, guards, rescues, boolean operators, assignments, safe navigation, blocks, lambdas, and nested boundaries.
176
+
177
+ A 49,500-case numeric grid compared scores with exact rational results. No difference exceeded `1e-8`; exact threshold equality still fails as F3 demonstrates.
178
+
179
+ Existing tests also cover suite unions, null-line exclusion, absent files, malformed reports, and separating loaded definitions from called multiline methods.
180
+
181
+ Taking the maximum hit count across suites is sufficient for covered-line union because scoring only asks whether each count is positive.
182
+
183
+ ## Upstream interpretation
184
+
185
+ ### Original CRAP definition
186
+
187
+ Alberto Savoia's original definition uses the same algebra, with coverage expressed as a percentage before division by 100.
188
+
189
+ It specifies basis path coverage, not line coverage. His 2011 retrospective repeats that requirement. [Original definition](https://www.artima.com/weblogs/viewpost.jsp?thread=210575), [author's retrospective](https://testing.googleblog.com/2011/02/this-code-is-crap.html).
190
+
191
+ Inference: line or branch totals do not establish which combinations of decisions were executed. Branch coverage alone would not establish original basis path coverage.
192
+
193
+ ### Implementations cited by the README
194
+
195
+ The three cited ports share the formula but use different coverage proxies and counting policies:
196
+
197
+ | Implementation | Inspected commit | Coverage input |
198
+ | --- | --- | --- |
199
+ | `unclebob/crap4java` | `69b561209f130ece728f19b0001e90df5a117c3a` | JaCoCo method instruction counters. |
200
+ | `unclebob/crap4clj` | `e90be2e7aa02c2ec5d6544e9cecddc6b73ad3e4d` | Weighted Cloverage forms, with LCOV line fallback. |
201
+ | `unclebob/crap4go` | `bee16dbdadb4af927a7792083f3cba2ae58841ed` | Weighted covered statements from Go coverage segments. |
202
+
203
+ Coverage sources: [Java](https://github.com/unclebob/crap4java/blob/69b561209f130ece728f19b0001e90df5a117c3a/src/crap4java/JacocoCoverageParser.java), [Clojure](https://github.com/unclebob/crap4clj/blob/e90be2e7aa02c2ec5d6544e9cecddc6b73ad3e4d/src/crap4clj/coverage.cljc), [Go](https://github.com/unclebob/crap4go/blob/bee16dbdadb4af927a7792083f3cba2ae58841ed/internal/coverage/coverage.go).
204
+
205
+ Formula sources: [Java](https://github.com/unclebob/crap4java/blob/69b561209f130ece728f19b0001e90df5a117c3a/src/crap4java/CrapScore.java), [Clojure](https://github.com/unclebob/crap4clj/blob/e90be2e7aa02c2ec5d6544e9cecddc6b73ad3e4d/src/crap4clj/crap.cljc), [Go](https://github.com/unclebob/crap4go/blob/bee16dbdadb4af927a7792083f3cba2ae58841ed/internal/crap/crap.go).
206
+
207
+ The ports also differ in extracted units and handling absent coverage. Their implementations cannot define a single complete Ruby contract.
208
+
209
+ Some upstream README examples contain arithmetic errors. Both Go and Clojure show CC 12, coverage 45%, and CRAP 130.2; the formula gives 35.958.
210
+
211
+ Clojure also shows CC 8, coverage 82%, and CRAP 3.4. The formula gives 8.373248, and a score below CC is impossible.
212
+
213
+ Example sources: [Go README](https://github.com/unclebob/crap4go/blob/bee16dbdadb4af927a7792083f3cba2ae58841ed/README.md), [Clojure README](https://github.com/unclebob/crap4clj/blob/e90be2e7aa02c2ec5d6544e9cecddc6b73ad3e4d/README.md).
214
+
215
+ ### Ruby reference policy
216
+
217
+ RuboCop `v1.92.1`, commit `aa228eb03094d66aca26664839ca14b10d76f702`, provides an established Ruby convention. CRAP does not require that convention.
218
+
219
+ Its complexity calculation counts known iteration blocks and block arguments, discounts repeated safe navigation on a local receiver, and excludes parameter-default decisions.
220
+
221
+ It counts each `when` clause once, matching this project. Its method detector also recognizes bare `define_method` calls with literal names.
222
+
223
+ Sources: [complexity counter](https://github.com/rubocop/rubocop/blob/aa228eb03094d66aca26664839ca14b10d76f702/lib/rubocop/cop/metrics/cyclomatic_complexity.rb), [iteration rules](https://github.com/rubocop/rubocop/blob/aa228eb03094d66aca26664839ca14b10d76f702/lib/rubocop/cop/metrics/utils/iterating_block.rb), [safe-navigation rules](https://github.com/rubocop/rubocop/blob/aa228eb03094d66aca26664839ca14b10d76f702/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb), [method detection](https://github.com/rubocop/rubocop/blob/aa228eb03094d66aca26664839ca14b10d76f702/lib/rubocop/cop/mixin/method_complexity.rb).
224
+
225
+ Ruby documents separate line, branch, and method coverage modes. Its documented modes do not include basis path coverage. [Ruby Coverage API](https://docs.ruby-lang.org/en/master/Coverage.html).
226
+
227
+ ## Evidence scope
228
+
229
+ F1 through F4 were reproduced using CRuby 3.3.11 and 4.0.9, Prism 1.9.0, and SimpleCov 1.3.2.
230
+
231
+ F1 through F3 include actual subprocess CLI runs with freshly generated SimpleCov reports. The nested-default example also executed successfully and installed its omitted method.
232
+
233
+ The parser matrix, numeric grid, and existing suite ran on CRuby 4.0.9. Ruby 3.4 execution was not attempted after dependency checking found missing `lefthook`.
234
+
235
+ Runtime coverage instrumentation can differ between Ruby versions. The audit observed different executable-line treatment for a pattern-matching `case` header between 3.3 and 4.0.
236
+
237
+ Upstream evidence came from primary publications, documentation, and fixed GitHub revisions. Upstream programs were inspected but not executed.
238
+
239
+ Prism 1.0.0 source contains the checked call/index node classes and generates their `safe_navigation?` predicates. This was a source check, not minimum-version execution.
240
+
241
+ Sources: [Prism node schema](https://github.com/ruby/prism/blob/163a2659260c6c74d8e7e02c5431fc61d17315c1/config.yml), [Ruby node generator](https://github.com/ruby/prism/blob/163a2659260c6c74d8e7e02c5431fc61d17315c1/templates/lib/prism/node.rb.erb).
242
+
243
+ No production code, dependencies, or existing tests were changed. Temporary probe scripts were removed after recording their source examples and results here.
244
+
245
+ ## Recommended sequence
246
+
247
+ 1. Fix heredoc location selection and discovery of explicit definitions in executable expressions, with real coverage regressions.
248
+ 2. Define ambiguous and unknown coverage behavior, including threshold enforcement, before reporting full coverage for shared definition lines.
249
+ 3. Make exact threshold equality reliable with a documented numeric comparison policy.
250
+ 4. Adopt and document one Ruby complexity convention, with explicit decisions for iterators, defaults, patterns, and safe navigation.
251
+ 5. Describe the result as CRAP using that convention and its coverage proxy. Avoid claims of complete Ruby analysis or original basis path measurement.
data/sig/crap4ruby.rbs CHANGED
@@ -1,5 +1,6 @@
1
1
  module Crap4Ruby
2
2
  VERSION: String
3
+ type score = Float | Rational
3
4
 
4
5
  class Error < StandardError
5
6
  end
@@ -8,12 +9,12 @@ module Crap4Ruby
8
9
  attr_reader name: String
9
10
  attr_reader namespace: String
10
11
  attr_reader complexity: Integer
11
- attr_reader lines: Array[Integer]
12
+ attr_reader lines: Array[Integer]?
12
13
  attr_reader path: String
13
- def self.new: (String name, String namespace, Integer complexity, Array[Integer] lines, String path) -> instance
14
- | (name: String, namespace: String, complexity: Integer, lines: Array[Integer], path: String) -> instance
14
+ def self.new: (String name, String namespace, Integer complexity, Array[Integer]? lines, String path) -> instance
15
+ | (name: String, namespace: String, complexity: Integer, lines: Array[Integer]?, path: String) -> instance
15
16
  alias self.[] self.new
16
- def with: (?name: String, ?namespace: String, ?complexity: Integer, ?lines: Array[Integer], ?path: String) -> instance
17
+ def with: (?name: String, ?namespace: String, ?complexity: Integer, ?lines: Array[Integer]?, ?path: String) -> instance
17
18
  end
18
19
 
19
20
  class Entry < Data
@@ -21,24 +22,36 @@ module Crap4Ruby
21
22
  attr_reader namespace: String
22
23
  attr_reader complexity: Integer
23
24
  attr_reader coverage: Float?
24
- attr_reader crap: Float?
25
+ attr_reader crap: score?
25
26
  attr_reader path: String
26
- def self.new: (String name, String namespace, Integer complexity, Float? coverage, Float? crap, String path) -> instance
27
- | (name: String, namespace: String, complexity: Integer, coverage: Float?, crap: Float?, path: String) -> instance
27
+ def self.new: (String name, String namespace, Integer complexity, Float? coverage, score? crap, String path) -> instance
28
+ | (name: String, namespace: String, complexity: Integer, coverage: Float?, crap: score?, path: String) -> instance
28
29
  alias self.[] self.new
29
- def with: (?name: String, ?namespace: String, ?complexity: Integer, ?coverage: Float?, ?crap: Float?, ?path: String) -> instance
30
+ def with: (?name: String, ?namespace: String, ?complexity: Integer, ?coverage: Float?, ?crap: score?, ?path: String) -> instance
30
31
  end
31
32
 
32
33
  class Analyzer
34
+ ITERATING_METHODS: Array[Symbol]
33
35
  def call: (String source, path: String) -> Array[MethodInfo]
34
36
  private
35
37
  def discover: (Prism::Node? node, Array[String] scope, bool singleton, String path) -> Array[MethodInfo]
38
+ def discover_class: (Prism::ClassNode | Prism::ModuleNode node, Array[String] scope, bool singleton, String path) -> Array[MethodInfo]
39
+ def discover_call: (Prism::CallNode node, Array[String] scope, bool singleton, String path) -> Array[MethodInfo]
36
40
  def discover_method: (Prism::DefNode node, Array[String] scope, bool singleton, String path) -> Array[MethodInfo]
41
+ def discover_block: (Prism::BlockNode block, String name, Array[String] scope, bool singleton, String path) -> Array[MethodInfo]
42
+ def defined_name: (Prism::Node node) -> String?
43
+ def method_owner: (Prism::DefNode node, Array[String] scope) -> Array[String]?
37
44
  def qualify: (Prism::Node? node, Array[String] scope, ?declaration: bool) -> Array[String]?
38
- def decisions: (Prism::Node? node) -> Integer
45
+ def decisions: (Prism::Node? node, ?Hash[Symbol, bool] seen, ?target: bool) -> Integer
46
+ def child_decisions: (Prism::Node node, Hash[Symbol, bool] seen, bool target) -> Integer
47
+ def assignment_target?: (Prism::Node node, Prism::Node child, bool target) -> bool
48
+ def decision?: (Prism::Node node) -> bool
49
+ def safe_navigation?: (Prism::Node node, Hash[Symbol, bool] seen) -> bool
50
+ def iteration?: (Prism::Node node) -> bool
39
51
  def boundary?: (Prism::Node node) -> bool
40
- def body_lines: (Prism::Node? node) -> Array[Integer]
41
- def collect_boundaries: (Prism::Node node, Array[Integer] excluded) -> void
52
+ def body_lines: (Prism::Node? node, after: Integer, ending: Prism::Location) -> Array[Integer]?
53
+ def trailing_code?: (Prism::Location location) -> bool
54
+ def body_end_line: (Prism::Node node, Array[Integer] excluded) -> Integer
42
55
  end
43
56
 
44
57
  type json = nil | bool | Integer | Float | String | Array[json] | Hash[String, json]
@@ -47,7 +60,7 @@ module Crap4Ruby
47
60
  @files: Hash[String, Array[Integer?]]
48
61
  def self.load: (String path, root: String) -> Coverage
49
62
  def initialize: (json suites, root: String) -> void
50
- def fraction: (MethodInfo method) -> Float?
63
+ def fraction: (MethodInfo method) -> Rational?
51
64
  private
52
65
  def add_suite: (json suite, String root) -> void
53
66
  def add_file: (String path, json data, String root) -> void
@@ -56,6 +69,7 @@ module Crap4Ruby
56
69
  module Discovery
57
70
  EXCLUDED: Array[String]
58
71
  def self.call: (root: String, source_roots: Array[String], paths: Array[String], changed: bool) -> Array[String]
72
+ def self.selection_roots: (String root, Array[String] source_roots, Array[String] existing) -> Array[String]
59
73
  def self.walk: (String root) -> Array[String]
60
74
  def self.git: (String root, *String arguments) -> String
61
75
  def self.changed_files: (String root) -> Array[String]
@@ -68,8 +82,9 @@ module Crap4Ruby
68
82
  module Report
69
83
  def self.sorted: (Array[Entry] entries) -> Array[Entry]
70
84
  def self.table: (Array[Entry] entries) -> String
85
+ def self.label: (String value) -> String
71
86
  def self.edn: (Array[Entry] entries) -> String
72
- def self.number: (Float? value) -> String
87
+ def self.number: (score? value) -> String
73
88
  def self.write: (Array[Entry] entries, root: String) -> String
74
89
  end
75
90
 
@@ -80,15 +95,16 @@ module Crap4Ruby
80
95
 
81
96
  class CLI
82
97
  type options = { root: String, source_roots: Array[String], changed: bool, coverage: String,
83
- ?help: bool, ?version: bool, ?no_coverage: bool, ?existing: bool, ?command: String, ?threshold: Float }
98
+ ?help: bool, ?version: bool, ?no_coverage: bool, ?no_save: bool, ?existing: bool, ?command: String, ?threshold: Rational }
84
99
  @stdout: _Output
85
100
  @stderr: _Output
86
101
  def initialize: (?stdout: _Output, ?stderr: _Output) -> void
87
102
  def run: (Array[String] arguments) -> Integer
88
103
  private
104
+ def analyze: (Array[String] files, Coverage? coverage) -> Array[Entry]
89
105
  def parse_options: (Array[String] arguments) -> [options, OptionParser, Array[String]]
90
106
  def validate_options: (options options) -> void
91
- def threshold_status: (Array[Entry] entries, Float? threshold) -> Integer
107
+ def threshold_status: (Array[Entry] entries, Rational? threshold) -> Integer
92
108
  def load_coverage: (options options, String root) -> Coverage
93
109
  def run_coverage: (String command, String root, String report) -> void
94
110
  def report_stamp: (String path) -> [Integer, Time, Time, Integer]?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crap4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Svyatov
@@ -52,6 +52,9 @@ files:
52
52
  - lib/crap4ruby/report.rb
53
53
  - lib/crap4ruby/score.rb
54
54
  - lib/crap4ruby/version.rb
55
+ - oss-audit-report.before.md
56
+ - oss-audit-report.md
57
+ - scoring-audit.md
55
58
  - sig/crap4ruby.rbs
56
59
  - sig/manifest.yaml
57
60
  - sig/stdlib.rbs