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 +4 -4
- data/docs/manual/02-cli-reference.md +12 -0
- data/docs/manual/10-mcp-server.md +8 -1
- data/lib/rigor/cli/triage_command.rb +8 -2
- data/lib/rigor/cli/triage_renderer.rb +4 -0
- data/lib/rigor/triage/catalogue.rb +16 -1
- data/lib/rigor/triage.rb +30 -7
- data/lib/rigor/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 775a0b6e3050294352d505366428814ab73348d2ced5ccf45842644c38752155
|
|
4
|
+
data.tar.gz: 7ec72c4aa56cbb43ae18dd3c1a029da3bb6746a604c4a3d72811b34b5d1c1439
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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(
|
|
41
|
-
selectors: build_selectors(
|
|
42
|
-
hotspots: build_hotspots(
|
|
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