rigortype 0.2.2 → 0.2.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a23952ba800fa7d807c8b8acc4d1cfbb3489024d91c3c30d687ebfdb75c7d1f5
4
- data.tar.gz: 1a301a820c1c0bd3c2946695ae59f8e00906d1ecebedc0fbfb1fa93da3f6a72a
3
+ metadata.gz: 775a0b6e3050294352d505366428814ab73348d2ced5ccf45842644c38752155
4
+ data.tar.gz: 7ec72c4aa56cbb43ae18dd3c1a029da3bb6746a604c4a3d72811b34b5d1c1439
5
5
  SHA512:
6
- metadata.gz: 6574512ee06d1eb87e42f697d7261eac8ecf9bba9ae4a8a4be6263fba188de5b9786babdcef7e9b2cf41ac4877010726d60f66b741af7b5295d6d3e98e5937cb
7
- data.tar.gz: d1bcccf23cac521597657aadd2f1c35d7a860998dd3fc8e02a7802c2dc0e9bf23ca3c0e6c368cdb9574cc1ac1e5ff2395f9dd5f164beae13541874d617886b19
6
+ metadata.gz: cc0650acb783740184fb76f0c5382fefe3950bd84011c84ccd2e23a60ff703519de94a294b39e96e11198748b2539917fae117972be7366dd06725ee54975935
7
+ data.tar.gz: d06b60ff922cfb4ab77ea680b5d624702a4f782b65c1dcb2e3f631793fe90cb4bb8302d50ac5a3656cbd1a1fe79e198cfee9c8641b037acf48906ae1aa63eeb8
@@ -232,6 +232,18 @@ rigor triage [paths]
232
232
  `--selectors-only`, and `--no-hints` select which sections print.
233
233
  `triage` is advisory and always exits `0` — it never gates a build.
234
234
 
235
+ By default the distribution, selectors, and hotspots sections count
236
+ only the **actionable** diagnostics (`error` + `warning`). `info`
237
+ diagnostics are excluded from these volume views — on a Rails project
238
+ they are dominated by plugin *recognition trace* (`Account.find
239
+ resolves to Account`, `users_path → GET /users`), positive "Rigor
240
+ resolved this" records that would otherwise bury the genuine signal
241
+ and skew the hotspot ranking toward the files with the most *working*
242
+ code. The summary line still reports the full `info` count, and
243
+ heuristic hints still see every diagnostic (so the `gem-without-rbs`
244
+ notice survives). Pass `--include-info` to route `info` into the
245
+ volume views as well.
246
+
235
247
  The **`selectors`** section is the by-(class, method) axis: it
236
248
  aggregates the structured `receiver_type` / `method_name` fields the
237
249
  diagnostics carry into `{receiver, method, count, files, rules}`
@@ -295,10 +295,17 @@ the most common error clusters.
295
295
  "hints": [
296
296
  { "id": "activesupport-core-ext", "confidence": "likely",
297
297
  "diagnostic_count": 365, "summary": "...", "action": "..." }
298
- ]
298
+ ],
299
+ "include_info": false
299
300
  }
300
301
  ```
301
302
 
303
+ By default the `distribution` / `selectors` / `hotspots` arrays count
304
+ only the actionable diagnostics (`error` + `warning`); `info` (mostly
305
+ plugin recognition trace) is excluded, so those counts do not sum to
306
+ `summary.total` and `include_info` is `false`. `summary.info` still
307
+ reports the full info count, and the hints still see every diagnostic.
308
+
302
309
  The `selectors` array is the by-(class, method) axis: each row is a
303
310
  dispatch target with its `count`, distinct-`files` spread, and
304
311
  per-`rule` breakdown, keyed on a normalised receiver class — so an
@@ -31,7 +31,8 @@ module Rigor
31
31
  diagnostics = analyze(configuration)
32
32
 
33
33
  report = Triage.analyze(diagnostics, top: options.fetch(:top),
34
- hints: options.fetch(:sections).include?(:hints))
34
+ hints: options.fetch(:sections).include?(:hints),
35
+ include_info: options.fetch(:include_info))
35
36
  renderer = TriageRenderer.new(report, sections: options.fetch(:sections))
36
37
  @out.puts(options.fetch(:format) == "json" ? renderer.json : renderer.text)
37
38
  0
@@ -40,12 +41,17 @@ module Rigor
40
41
  private
41
42
 
42
43
  def parse_options
43
- options = { config: nil, format: "text", top: 10, sections: DEFAULT_SECTIONS }
44
+ options = { config: nil, format: "text", top: 10, sections: DEFAULT_SECTIONS, include_info: false }
44
45
  OptionParser.new do |opts|
45
46
  opts.banner = USAGE
46
47
  Options.add_config(opts, options)
47
48
  opts.on("--format=FORMAT", "Output format: text (default) or json") { |v| options[:format] = v }
48
49
  opts.on("--top=N", Integer, "Hotspot-file count (default 10)") { |v| options[:top] = v }
50
+ opts.on("--include-info",
51
+ "Route info diagnostics into distribution / selectors / hotspots " \
52
+ "(excluded by default — mostly plugin recognition trace)") do
53
+ options[:include_info] = true
54
+ end
49
55
  opts.on("--hints-only", "Print only the heuristic-hints section") { options[:sections] = %i[hints] }
50
56
  opts.on("--no-hints", "Print distribution + selectors + hotspots only") do
51
57
  options[:sections] = %i[distribution selectors hotspots]
@@ -37,6 +37,10 @@ module Rigor
37
37
  max = @report.distribution.map(&:count).max || 1
38
38
  lines = ["Diagnostic distribution — #{s.total} total " \
39
39
  "(#{s.error} error / #{s.warning} warning#{" / #{s.info} info" if s.info.positive?})"]
40
+ if !@report.include_info && s.info.positive?
41
+ lines << " #{s.info} info diagnostic(s) hidden below " \
42
+ "(mostly plugin recognition trace) — pass --include-info to route them"
43
+ end
40
44
  @report.distribution.each do |row|
41
45
  lines << format(" %<rule>-32s %<count>5d %<bar>s",
42
46
  rule: row.rule, count: row.count, bar: bar(row.count, max))
@@ -87,12 +87,27 @@ module Rigor
87
87
  GENUINE_BUG_MAX_COUNT = 5 # rule total ≤ N → "likely genuine bug"
88
88
  private_constant :SYSTEMIC_THRESHOLD, :MONKEY_PATCH_MIN_FILES, :GENUINE_BUG_MAX_COUNT
89
89
 
90
+ # WD6 (ADR-23): H5 (systemic cluster) and H6 (genuine bugs) are
91
+ # the only count-based, severity-agnostic recognisers, so they
92
+ # alone risk reading plugin recognition trace (`:info`
93
+ # `*.model-call` / `*.helper`, …) as a "systemic cluster" or a
94
+ # "genuine bug" — frightening working code. They are guarded
95
+ # against `:info` unless `include_info` restores the pre-v0.2.3
96
+ # behaviour. Every other recogniser keys on an error/warning rule
97
+ # (H1/H2/H2K/H4/H7) or intentionally reads an info notice
98
+ # (H3 — the `gem-without-rbs` `rbs.coverage.missing-gem`), so the
99
+ # full pool is correct for them.
100
+ INFO_GUARDED = %i[h5_systemic_cluster h6_genuine_bugs].freeze
101
+ private_constant :INFO_GUARDED
102
+
90
103
  # @param diagnostics [Array<Analysis::Diagnostic>]
104
+ # @param include_info [Boolean] let H5/H6 see `:info` diagnostics
91
105
  # @return [Array<Hint>]
92
- def recognise(diagnostics)
106
+ def recognise(diagnostics, include_info: false)
93
107
  claimed = {}.compare_by_identity
94
108
  recognisers.filter_map do |recogniser|
95
109
  pool = diagnostics.reject { |d| claimed[d] }
110
+ pool = pool.reject { |d| d.severity == :info } if INFO_GUARDED.include?(recogniser) && !include_info
96
111
  hint, matched = send(recogniser, pool)
97
112
  next unless hint
98
113
 
data/lib/rigor/triage.rb CHANGED
@@ -26,21 +26,40 @@ module Rigor
26
26
  # receiver); `files` is the distinct-file count (a systemic vs.
27
27
  # localised signal); `rules` is the per-rule breakdown.
28
28
  Selector = Data.define(:receiver, :method_name, :count, :files, :rules)
29
- Report = Data.define(:summary, :distribution, :selectors, :hotspots, :hints)
29
+ Report = Data.define(:summary, :distribution, :selectors, :hotspots, :hints, :include_info)
30
30
 
31
31
  module_function
32
32
 
33
+ # WD6 (ADR-23): the volume views — distribution / selectors /
34
+ # hotspots — route only the *actionable* diagnostics (error +
35
+ # warning) by default. Plugin-emitted `:info` diagnostics are
36
+ # overwhelmingly recognition trace (`plugin.activerecord.model-call`,
37
+ # `plugin.rails-routes.helper`, …) — positive "Rigor resolved this
38
+ # call" records, not problems — and on a real Rails app they swamp
39
+ # the genuine error/warning signal (the field trip: 257 of 267
40
+ # diagnostics were such trace) and invert the hotspot ranking
41
+ # towards the files with the *most working* code. The summary still
42
+ # reports the full info count, and `include_info: true` (the
43
+ # `--include-info` flag) restores the pre-v0.2.3 behaviour. Hints
44
+ # always see the full stream so the `gem-without-rbs` notice (an
45
+ # info-severity `rbs.coverage.missing-gem`) survives; the
46
+ # count-based H5/H6 recognisers guard against info themselves so
47
+ # recognition trace never reads as a bug.
48
+ #
33
49
  # @param diagnostics [Array<Analysis::Diagnostic>]
34
50
  # @param top [Integer] hotspot-file cap
35
51
  # @param hints [Boolean] run the heuristic catalogue
52
+ # @param include_info [Boolean] route info into the volume views
36
53
  # @return [Report]
37
- def analyze(diagnostics, top: 10, hints: true)
54
+ def analyze(diagnostics, top: 10, hints: true, include_info: false)
55
+ routed = include_info ? diagnostics : diagnostics.reject { |d| d.severity == :info }
38
56
  Report.new(
39
57
  summary: build_summary(diagnostics),
40
- distribution: build_distribution(diagnostics),
41
- selectors: build_selectors(diagnostics),
42
- hotspots: build_hotspots(diagnostics, top),
43
- hints: hints ? Catalogue.recognise(diagnostics) : []
58
+ distribution: build_distribution(routed),
59
+ selectors: build_selectors(routed),
60
+ hotspots: build_hotspots(routed, top),
61
+ hints: hints ? Catalogue.recognise(diagnostics, include_info: include_info) : [],
62
+ include_info: include_info
44
63
  )
45
64
  end
46
65
 
@@ -150,7 +169,11 @@ module Rigor
150
169
  "hotspots" => report.hotspots.map do |h|
151
170
  { "file" => h.file, "count" => h.count, "by_rule" => h.by_rule }
152
171
  end,
153
- "hints" => report.hints.map(&:to_h)
172
+ "hints" => report.hints.map(&:to_h),
173
+ # WD6: false means distribution / selectors / hotspots above
174
+ # exclude `:info` (their counts will not sum to summary.total);
175
+ # the summary's `info` field still reports the full count.
176
+ "include_info" => report.include_info
154
177
  }
155
178
  end
156
179
  end
data/lib/rigor/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rigor
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors