rigortype 0.2.1 → 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/README.md +41 -14
- data/docs/handbook/01-getting-started.md +311 -0
- data/docs/handbook/02-everyday-types.md +337 -0
- data/docs/handbook/03-narrowing.md +359 -0
- data/docs/handbook/04-tuples-and-shapes.md +321 -0
- data/docs/handbook/05-methods-and-blocks.md +339 -0
- data/docs/handbook/06-classes.md +305 -0
- data/docs/handbook/07-rbs-and-extended.md +427 -0
- data/docs/handbook/08-understanding-errors.md +373 -0
- data/docs/handbook/09-plugins.md +241 -0
- data/docs/handbook/10-sorbet.md +347 -0
- data/docs/handbook/11-sig-gen.md +312 -0
- data/docs/handbook/12-lightweight-hkt.md +333 -0
- data/docs/handbook/README.md +275 -0
- data/docs/handbook/appendix-elixir.md +370 -0
- data/docs/handbook/appendix-go.md +399 -0
- data/docs/handbook/appendix-java-csharp.md +470 -0
- data/docs/handbook/appendix-liskov.md +580 -0
- data/docs/handbook/appendix-mypy.md +370 -0
- data/docs/handbook/appendix-phpstan.md +338 -0
- data/docs/handbook/appendix-protocols-and-structural-typing.md +292 -0
- data/docs/handbook/appendix-rust.md +446 -0
- data/docs/handbook/appendix-steep.md +336 -0
- data/docs/handbook/appendix-type-theory.md +1662 -0
- data/docs/handbook/appendix-typeprof.md +416 -0
- data/docs/handbook/appendix-typescript.md +332 -0
- data/docs/install.md +189 -0
- data/docs/llms.txt +72 -0
- data/docs/manual/01-installation.md +342 -0
- data/docs/manual/02-cli-reference.md +569 -0
- data/docs/manual/03-configuration.md +152 -0
- data/docs/manual/04-diagnostics.md +206 -0
- data/docs/manual/05-inspecting-types.md +109 -0
- data/docs/manual/06-baseline.md +104 -0
- data/docs/manual/07-plugins.md +92 -0
- data/docs/manual/08-skills.md +143 -0
- data/docs/manual/09-editor-integration.md +245 -0
- data/docs/manual/10-mcp-server.md +539 -0
- data/docs/manual/11-ci.md +274 -0
- data/docs/manual/12-caching.md +116 -0
- data/docs/manual/13-troubleshooting.md +120 -0
- data/docs/manual/14-rails-quickstart.md +332 -0
- data/docs/manual/15-type-protection-coverage.md +204 -0
- data/docs/manual/16-rbs-extended-annotations.md +190 -0
- data/docs/manual/17-driving-improvement.md +160 -0
- data/docs/manual/README.md +87 -0
- data/docs/manual/ci-templates/README.md +58 -0
- data/docs/manual/plugins/README.md +86 -0
- data/docs/manual/plugins/rigor-actioncable.md +78 -0
- data/docs/manual/plugins/rigor-actionmailer.md +74 -0
- data/docs/manual/plugins/rigor-actionpack.md +80 -0
- data/docs/manual/plugins/rigor-activejob.md +58 -0
- data/docs/manual/plugins/rigor-activerecord.md +102 -0
- data/docs/manual/plugins/rigor-activestorage.md +74 -0
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +86 -0
- data/docs/manual/plugins/rigor-devise.md +70 -0
- data/docs/manual/plugins/rigor-dry-schema.md +56 -0
- data/docs/manual/plugins/rigor-dry-struct.md +60 -0
- data/docs/manual/plugins/rigor-dry-types.md +59 -0
- data/docs/manual/plugins/rigor-dry-validation.md +62 -0
- data/docs/manual/plugins/rigor-factorybot.md +76 -0
- data/docs/manual/plugins/rigor-graphql.md +89 -0
- data/docs/manual/plugins/rigor-hanami.md +83 -0
- data/docs/manual/plugins/rigor-mangrove.md +73 -0
- data/docs/manual/plugins/rigor-minitest.md +86 -0
- data/docs/manual/plugins/rigor-pundit.md +72 -0
- data/docs/manual/plugins/rigor-rails-i18n.md +92 -0
- data/docs/manual/plugins/rigor-rails-routes.md +94 -0
- data/docs/manual/plugins/rigor-rails.md +44 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +83 -0
- data/docs/manual/plugins/rigor-rspec-rails.md +72 -0
- data/docs/manual/plugins/rigor-rspec.md +86 -0
- data/docs/manual/plugins/rigor-shoulda-matchers.md +78 -0
- data/docs/manual/plugins/rigor-sidekiq.md +78 -0
- data/docs/manual/plugins/rigor-sinatra.md +61 -0
- data/docs/manual/plugins/rigor-sorbet.md +63 -0
- data/docs/manual/plugins/rigor-statesman.md +75 -0
- data/docs/manual/plugins/rigor-typescript-utility-types.md +71 -0
- data/exe/rigor +1 -1
- data/lib/rigor/analysis/incremental_session.rb +4 -2
- data/lib/rigor/analysis/run_stats.rb +13 -1
- data/lib/rigor/analysis/runner.rb +54 -12
- data/lib/rigor/cli/check_command.rb +1 -1
- data/lib/rigor/cli/docs_command.rb +248 -0
- data/lib/rigor/cli/skill_command.rb +103 -41
- data/lib/rigor/cli/skill_describe.rb +346 -0
- data/lib/rigor/cli/triage_command.rb +8 -2
- data/lib/rigor/cli/triage_renderer.rb +4 -0
- data/lib/rigor/cli.rb +25 -3
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +124 -32
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +37 -6
- data/lib/rigor/inference/scope_indexer.rb +87 -89
- data/lib/rigor/plugin/isolation.rb +5 -5
- data/lib/rigor/plugin/loader.rb +4 -2
- data/lib/rigor/triage/catalogue.rb +16 -1
- data/lib/rigor/triage.rb +30 -7
- data/lib/rigor/version.rb +1 -1
- data/skills/rigor-ask/SKILL.md +172 -0
- data/skills/rigor-doctor/SKILL.md +87 -0
- data/skills/rigor-editor-setup/SKILL.md +114 -0
- data/skills/rigor-mcp-setup/SKILL.md +117 -0
- data/skills/rigor-monkeypatch-resolve/SKILL.md +79 -0
- data/skills/rigor-next-steps/SKILL.md +113 -0
- data/skills/rigor-plugin-tune/SKILL.md +79 -0
- data/skills/rigor-protection-uplift/SKILL.md +133 -0
- data/skills/rigor-rbs-setup/SKILL.md +128 -0
- data/skills/rigor-upgrade/SKILL.md +79 -0
- metadata +90 -1
data/lib/rigor/plugin/loader.rb
CHANGED
|
@@ -183,8 +183,10 @@ module Rigor
|
|
|
183
183
|
Plugin.registered_for(newly_registered.first)
|
|
184
184
|
else
|
|
185
185
|
raise LoadError.new(
|
|
186
|
-
"plugin gem #{entry[:gem].inspect}
|
|
187
|
-
"(#{newly_registered.sort.inspect})
|
|
186
|
+
"plugin gem #{entry[:gem].inspect} bundles #{newly_registered.size} plugins " \
|
|
187
|
+
"(#{newly_registered.sort.inspect}) and cannot be activated as a single `plugins:` entry — " \
|
|
188
|
+
"it is a convenience meta-gem. List the individual plugin gems you want in `plugins:` " \
|
|
189
|
+
"(e.g. `rigor-#{newly_registered.min}`), or select one with an explicit `id:` field.",
|
|
188
190
|
plugin_ref: entry[:gem]
|
|
189
191
|
)
|
|
190
192
|
end
|
|
@@ -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
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rigor-ask
|
|
3
|
+
description: |
|
|
4
|
+
Rigor is a niche, fast-moving Ruby type checker; its rules, flags, and type behaviour are version-specific, so what you "remember" about it is likely wrong or stale — do NOT answer from memory or guess. For ANY question about Rigor, use this skill and investigate procedurally: run `rigor docs` (handbook + manual, bundled OFFLINE and version-matched), `rigor explain` for a diagnostic id, and for the user's own code `rigor check` / `annotate` / `type-of`, then answer only from what you read. Covers: why a line is flagged or if it's a false positive; the type model (narrowing, refinements, `Dynamic`, RBS); config keys, flags, baselines; comparisons to Sorbet, Steep, mypy, PHPStan; whether it handles Rails, RSpec, or a gem; writing an RBS signature; "what is Rigor / why use it / is it right for us?". Trigger on any Rigor mention seeking understanding — even casual, comparative, or grumbling. Skip only when Rigor isn't mentioned, or it's purely "set it up / fix / reduce it for me" (→ rigor-next-steps).
|
|
5
|
+
license: MPL-2.0
|
|
6
|
+
metadata:
|
|
7
|
+
version: 0.2.0
|
|
8
|
+
homepage: https://github.com/rigortype/rigor
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Ask Rigor anything
|
|
12
|
+
|
|
13
|
+
Someone has a question about Rigor. It might be about a diagnostic, the
|
|
14
|
+
type model, a flag, how Rigor stacks up against another type checker,
|
|
15
|
+
whether Rigor can handle their framework, how to type a method — or just
|
|
16
|
+
"what is this, and should I use it?" Whatever it is, **answer from the
|
|
17
|
+
source, not from memory.**
|
|
18
|
+
|
|
19
|
+
Two things make that easy, and you have both offline:
|
|
20
|
+
|
|
21
|
+
- **Rigor's own docs ship inside the gem.** `rigor docs` serves the full
|
|
22
|
+
handbook and manual, always matching the user's installed version, no
|
|
23
|
+
network. This is the authoritative copy: a rule's exact firing
|
|
24
|
+
condition, a flag's spelling, a config default — all drift release to
|
|
25
|
+
release, and `rigor docs` is the copy that shipped with *this* install,
|
|
26
|
+
so an answer drawn from it cannot disagree with the binary they run.
|
|
27
|
+
- **Rigor can read the user's actual code.** When the question is about
|
|
28
|
+
*their* program — "why is this flagged?", "what type does Rigor see
|
|
29
|
+
here?", "how well-typed is my project?" — `rigor check` / `annotate` /
|
|
30
|
+
`type-of` / `triage` / `coverage` answer from what Rigor inferred. A
|
|
31
|
+
concrete inferred type beats any abstract explanation.
|
|
32
|
+
|
|
33
|
+
This is the user's shortcut: they only ever need to remember two skills —
|
|
34
|
+
**`rigor-next-steps`** ("what should we do next?") and **`rigor-ask`**
|
|
35
|
+
("answer this about Rigor"). They ask in plain language; *you* turn it
|
|
36
|
+
into the right lookup or analysis so they never have to remember the
|
|
37
|
+
command.
|
|
38
|
+
|
|
39
|
+
## The toolbox
|
|
40
|
+
|
|
41
|
+
Everything here is read-only and needs no network.
|
|
42
|
+
|
|
43
|
+
### Reading the docs
|
|
44
|
+
|
|
45
|
+
| Command | Use |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `rigor docs` | The offline doc index (`llms.txt`) — the map. Start here when you don't know which page. |
|
|
48
|
+
| `rigor docs --list [manual\|handbook]` | List every bundled page with its path (optionally one category). |
|
|
49
|
+
| `rigor docs <name>` | Print a page. `<name>` is a category-qualified path (`handbook/03-narrowing`), a prefixed basename (`03-narrowing`), or a unique short name (`narrowing`). Pages that exist in **both** trees (e.g. `plugins`) must be qualified — `manual/07-plugins` vs `handbook/09-plugins`. |
|
|
50
|
+
| `rigor explain <rule>` | The catalogue entry for a diagnostic id (`rigor explain call.undefined-method`) — what it means, why it fires, how to address it. |
|
|
51
|
+
|
|
52
|
+
### Grounding the answer in the user's code
|
|
53
|
+
|
|
54
|
+
| Command | Use |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `rigor check <path>` | Run the analysis. Scope it to a file or directory for a quick answer — don't analyse the whole project just to settle one question. `--format json` exposes structured fields (`receiver_type`, `method_name`, `evidence_tier`, …). |
|
|
57
|
+
| `rigor annotate <file>` | Reprint the file with the inferred type of each line in the margin — *what Rigor actually sees*. |
|
|
58
|
+
| `rigor type-of <file>:<line>:<col>` | The inferred type at one position. |
|
|
59
|
+
| `rigor triage` | Cluster the project's diagnostics by rule / receiver / method — for "what's the shape of my errors?". |
|
|
60
|
+
| `rigor coverage [--protection]` | Type / type-protection coverage — for "how well-typed is this?" and "where are the holes?". |
|
|
61
|
+
| `rigor plugins` | Which plugins are installed and enabled *here* — the honest answer to "does Rigor support <gem/framework>?". |
|
|
62
|
+
| `rigor sig-gen <path>` | Generate RBS for code — for "how do I type this?". Offer it and show the result; this project prefers sig-gen over hand-written RBS. |
|
|
63
|
+
|
|
64
|
+
## Where the answer lives
|
|
65
|
+
|
|
66
|
+
Classify the question, then go to the page(s) — and, for anything about
|
|
67
|
+
*their* code, the command(s) — that own it. When unsure where a page is,
|
|
68
|
+
`rigor docs` (the index) or `rigor docs --list handbook` routes you.
|
|
69
|
+
|
|
70
|
+
| The question is about… | Go to |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| **A specific diagnostic** — "why is this flagged?", "what does this error mean?", "is this a false positive?" | `rigor explain <rule>`, then `rigor docs diagnostics`. If it's *their* code, also `rigor annotate <file>` / `rigor type-of` to see the inferred types the rule fired on. |
|
|
73
|
+
| **The type model / a concept** — narrowing, refinements, tuple & hash shapes, `Dynamic`, RBS interop, lightweight HKT | The handbook: `rigor docs --list handbook`, then the chapter — `handbook/03-narrowing`, `04-tuples-and-shapes`, `07-rbs-and-extended`, `12-lightweight-hkt`, … |
|
|
74
|
+
| **Operating Rigor** — a config key, CLI flag, baseline, plugins, CI, caching | The manual: `rigor docs configuration`, `cli-reference`, `baseline`, `manual/07-plugins`, `ci`, `caching`, `troubleshooting`. |
|
|
75
|
+
| **How Rigor compares to another tool** — Sorbet, Steep, RBS, TypeScript, mypy, PHPStan, TypeProf, Go, Rust, Java/C# | The chapter/appendix written for exactly that: `handbook/10-sorbet`, `appendix-steep`, `appendix-typescript`, `appendix-mypy`, `appendix-phpstan`, `appendix-typeprof`, `appendix-rust`, `appendix-go`, `appendix-java-csharp` (`rigor docs --list handbook` shows them all). |
|
|
76
|
+
| **Whether Rigor can do X** — generics, Rails, RSpec, a specific gem, concurrency | The handbook for the language feature; for framework/gem support, **`rigor plugins`** (what's actually available in *this* install) plus the per-plugin page `rigor docs rigor-<gem>` (e.g. `rigor docs rigor-sidekiq`) and the catalogue `rigor docs --list manual`. |
|
|
77
|
+
| **Writing a type / RBS** — "how do I type this?", an annotation, a signature | Handbook `07-rbs-and-extended` + `11-sig-gen`; manual `rbs-extended-annotations`. Then offer `rigor sig-gen <path>` to generate it (preferred over hand-RBS) and show the output. |
|
|
78
|
+
| **What Rigor is / why use it / is it right for me** | Handbook `01-getting-started` for the pitch, `handbook/02-everyday-types` for a quick mental model of the type zoo. Ground "is it right for *my* project" in a scoped `rigor check` / `rigor coverage` so they see Rigor on their real code. |
|
|
79
|
+
|
|
80
|
+
## Answer from the page, name the page
|
|
81
|
+
|
|
82
|
+
Quote or paraphrase the relevant passage and **say which page you drew
|
|
83
|
+
from** (e.g. "per `rigor docs handbook/03-narrowing` …"), so the user can
|
|
84
|
+
re-read it with the same command. Prefer the doc's own wording over a
|
|
85
|
+
remembered approximation. When you ran a command against their code, show
|
|
86
|
+
the relevant line of output — a concrete inferred type is more convincing
|
|
87
|
+
than prose, and it proves the answer rather than asserting it.
|
|
88
|
+
|
|
89
|
+
## When the question is really "do X for me"
|
|
90
|
+
|
|
91
|
+
Some questions are a task in disguise: *"how do I get Rigor into CI?"*,
|
|
92
|
+
*"how do I shrink this baseline?"*, *"how do I set Rigor up here?"* The
|
|
93
|
+
useful reply is **short**: orient the user — what the thing is, the one
|
|
94
|
+
decision that actually matters, the rough shape of it — then **hand the
|
|
95
|
+
doing to the skill built for it.** Resist pasting the full procedure
|
|
96
|
+
inline (the entire CI workflow YAML, the whole baseline-reduction loop):
|
|
97
|
+
that skill owns the steps, keeps them correct, and updates as the tool
|
|
98
|
+
moves, so duplicating them here only bloats the answer and drifts out of
|
|
99
|
+
date. The line is *explaining* the thing (yours) versus *wiring it in*
|
|
100
|
+
(the setup skill's).
|
|
101
|
+
|
|
102
|
+
A good hand-off is two or three sentences of orientation plus the pointer:
|
|
103
|
+
|
|
104
|
+
- setup / "what next?" → **`rigor-next-steps`** (it probes the project and routes)
|
|
105
|
+
- CI → **`rigor-ci-setup`** · editor → **`rigor-editor-setup`** · MCP agent → **`rigor-mcp-setup`**
|
|
106
|
+
- baseline reduction → **`rigor-baseline-reduce`** · coverage holes → **`rigor-protection-uplift`**
|
|
107
|
+
- a missing gem/DSL → **`rigor-plugin-author`** · monkey-patch clusters → **`rigor-monkeypatch-resolve`**
|
|
108
|
+
|
|
109
|
+
When in doubt, give less and point — it respects the user's "two skills
|
|
110
|
+
to remember" promise and keeps each answer to the part only `rigor-ask`
|
|
111
|
+
can give.
|
|
112
|
+
|
|
113
|
+
## If the docs don't cover it
|
|
114
|
+
|
|
115
|
+
The bundled set is the **drive-Rigor** corpus (manual + handbook). The
|
|
116
|
+
normative **type specification**, the internal spec, and the ADRs are
|
|
117
|
+
contributor-facing and stay web-only — they are *not* in `rigor docs`; if
|
|
118
|
+
a question genuinely needs them, say so and point at
|
|
119
|
+
<https://rigor.typedduck.fail/llms.txt> rather than guessing.
|
|
120
|
+
|
|
121
|
+
But before you defer, remember Rigor installs from RubyGems **with its
|
|
122
|
+
full source** — the per-plugin pages under the gem's `docs/manual/plugins/`,
|
|
123
|
+
the analyzer and plugin code under `lib/`. For a detail no doc page spells
|
|
124
|
+
out (a plugin's exact rule, a default baked into the code), reading the
|
|
125
|
+
bundled file directly is a perfectly good way to ground the answer, and
|
|
126
|
+
beats a guess. The rule that never bends: **never invent a flag, rule id,
|
|
127
|
+
config key, behaviour, or command output** — read the page, read the
|
|
128
|
+
source, or run the command, and quote only output you actually saw. A
|
|
129
|
+
confident wrong answer about a type checker is worse than "let me check."
|
|
130
|
+
|
|
131
|
+
## Examples
|
|
132
|
+
|
|
133
|
+
**A diagnostic on their code** — *"Why is Rigor flagging `s.lenght`?"*
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
rigor explain call.undefined-method # what the rule means and why it fires
|
|
137
|
+
rigor annotate demo.rb # the inferred type of `s` on that line
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Answer from both: Rigor inferred a concrete `String` receiver for `s`,
|
|
141
|
+
and `String` has no `lenght` (a typo for `length`) — grounded in what
|
|
142
|
+
`annotate` showed, not in a guess.
|
|
143
|
+
|
|
144
|
+
**A comparison** — *"How is Rigor different from Sorbet?"*
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
rigor docs handbook/10-sorbet # the chapter written for this
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Answer from the chapter's framing (RBS-superset, gradual `Dynamic`,
|
|
151
|
+
inference-first) rather than a remembered summary, and name it so they
|
|
152
|
+
can read on.
|
|
153
|
+
|
|
154
|
+
**A capability** — *"Does Rigor understand our Sidekiq workers?"*
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
rigor plugins # is rigor-sidekiq enabled in THIS project?
|
|
158
|
+
rigor docs rigor-sidekiq # the per-plugin page: what it teaches Rigor
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Answer from what's actually installed, plus — if useful — a scoped
|
|
162
|
+
`rigor check app/workers` so they see Rigor on their real workers.
|
|
163
|
+
|
|
164
|
+
**Authoring** — *"How do I type this method?"*
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
rigor sig-gen path/to/file.rb # generate the RBS, show it
|
|
168
|
+
rigor docs handbook/07-rbs-and-extended
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Generate it, show the signature, and explain it from the handbook —
|
|
172
|
+
preferring sig-gen's output over hand-written RBS.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rigor-doctor
|
|
3
|
+
description: |
|
|
4
|
+
Validate that a project's Rigor setup is actually healthy — config parses with no silently-inert values, every configured plugin loads, the baseline is not stale, and the bundled paths resolve — by running Rigor's existing validators and interpreting them. Triggers: "is my Rigor setup correct?", "check my rigor config", "rigor diagnostics look wrong / suspicious", "validate rigor setup", "why is rigor reporting nothing / everything?". NOT for first-time setup (use rigor-project-init) or for working real diagnostics down (use rigor-baseline-reduce).
|
|
5
|
+
license: MPL-2.0
|
|
6
|
+
metadata:
|
|
7
|
+
version: 0.1.0
|
|
8
|
+
homepage: https://github.com/rigortype/rigor
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Rigor Doctor
|
|
12
|
+
|
|
13
|
+
`rigor skill describe` reports what *exists* (presence checks). This skill
|
|
14
|
+
goes a level deeper: it *runs* Rigor's validators to confirm the setup is
|
|
15
|
+
actually working — the difference between "a `.rigor.yml` is present" and
|
|
16
|
+
"it parses, loads its plugins, and analyses the right files." Use it when
|
|
17
|
+
the diagnostics look wrong (suspiciously zero, or suspiciously many) or
|
|
18
|
+
after editing the config.
|
|
19
|
+
|
|
20
|
+
It needs **no special command** — it orchestrates checks Rigor already
|
|
21
|
+
ships and interprets the results.
|
|
22
|
+
|
|
23
|
+
## Checks
|
|
24
|
+
|
|
25
|
+
### 1. Config resolves with nothing silently inert
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
rigor check --format json # read the `config_warnings` array
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`rigor check` audits the config and emits `config_warnings` for the typo
|
|
32
|
+
class whose only symptom is a confusing downstream error: a
|
|
33
|
+
`signature_paths:` that is missing / not a directory / holds no `.rbs`
|
|
34
|
+
(which would turn every covered call into a false `call.undefined-method`
|
|
35
|
+
at `evidence_tier: high`), a `libraries:` name RBS does not recognise, a
|
|
36
|
+
`disable:` / `severity_overrides:` id naming no real rule, or a missing
|
|
37
|
+
`bundler` / `rbs_collection` path. **Each warning here is a real
|
|
38
|
+
misconfiguration — fix it.** None appearing is the healthy state.
|
|
39
|
+
|
|
40
|
+
### 2. Every configured plugin loads
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
rigor plugins --strict
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Reports the activation status of each plugin in `plugins:`; `--strict`
|
|
47
|
+
exits non-zero on any failure. A failure is usually a misspelled id or a
|
|
48
|
+
plugin whose `signature_paths:` did not resolve. Fix it, or the plugin's
|
|
49
|
+
type knowledge is silently absent.
|
|
50
|
+
|
|
51
|
+
### 3. The baseline is not stale (if one exists)
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
rigor baseline drift
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Shows whether the live diagnostics have drifted from `.rigor-baseline.yml`
|
|
58
|
+
— entries the baseline ignores that no longer occur (safe to prune) and
|
|
59
|
+
new diagnostics outside the envelope. A large drift means the baseline
|
|
60
|
+
needs regenerating (often after an upgrade — see `rigor-upgrade`).
|
|
61
|
+
|
|
62
|
+
### 4. The analysis is actually seeing your code
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
rigor check --format json # check the "Ruby source files" count
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If the file count is `0` or far below your project size, `paths:` /
|
|
69
|
+
`exclude:` are mis-scoped, or the command is running from the wrong
|
|
70
|
+
directory. The analysis is only as good as the files it reads.
|
|
71
|
+
|
|
72
|
+
## Interpreting the result
|
|
73
|
+
|
|
74
|
+
- **All clean** → the setup is healthy; any diagnostics are about the
|
|
75
|
+
code, not the configuration. Move on to `rigor-baseline-reduce` or
|
|
76
|
+
`rigor-protection-uplift`.
|
|
77
|
+
- **A `config_warning` or a plugin failure** → that is the real problem;
|
|
78
|
+
fixing it usually resolves a whole cluster of confusing downstream
|
|
79
|
+
diagnostics at once.
|
|
80
|
+
|
|
81
|
+
For deeper symptoms (hover shows `untyped` everywhere, completion empty,
|
|
82
|
+
LSP silent) see the manual's troubleshooting:
|
|
83
|
+
<https://github.com/rigortype/rigor/blob/master/docs/manual/13-troubleshooting.md>
|
|
84
|
+
|
|
85
|
+
## Next step
|
|
86
|
+
|
|
87
|
+
Re-run `rigor skill describe` for the recommended next move.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rigor-editor-setup
|
|
3
|
+
description: |
|
|
4
|
+
Wire Rigor's bundled language server (`rigor lsp`) into the developer's editor for live diagnostics, hover-to-type, outline, and type-aware completion. The per-editor config snippets live in the manual; this skill identifies the editor, applies the right one, and verifies the server attaches. Triggers: "set up Rigor in my editor", "rigor LSP / language server", "live Rigor diagnostics in VS Code / Neovim / Helix / Emacs", "hover types in my editor". NOT for CI integration (use rigor-ci-setup) or first-time project setup (use rigor-project-init).
|
|
5
|
+
license: MPL-2.0
|
|
6
|
+
metadata:
|
|
7
|
+
version: 0.1.0
|
|
8
|
+
homepage: https://github.com/rigortype/rigor
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Rigor Editor Setup
|
|
12
|
+
|
|
13
|
+
`rigor lsp` is the in-process Language Server bundled with the
|
|
14
|
+
`rigortype` gem. It speaks LSP over stdio and turns Rigor's analyzer
|
|
15
|
+
into a live editor experience: diagnostics as you type, hover-to-type,
|
|
16
|
+
an outline view, and type-aware completion. This skill wires it into the
|
|
17
|
+
developer's editor.
|
|
18
|
+
|
|
19
|
+
The authoritative, per-editor configuration lives in the manual. With
|
|
20
|
+
Rigor installed, read it **offline** with no network round-trip:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
rigor docs editor-integration
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
(Web fallback, only before Rigor is installed:
|
|
27
|
+
**[Rigor LSP — Editor Integration](https://github.com/rigortype/rigor/blob/master/docs/manual/09-editor-integration.md)**.)
|
|
28
|
+
This skill is the *workflow* around it (identify the editor → apply the
|
|
29
|
+
manual's snippet → verify), so it does not duplicate (and cannot
|
|
30
|
+
stale-out) the config details.
|
|
31
|
+
|
|
32
|
+
## When to use
|
|
33
|
+
|
|
34
|
+
- A developer wants Rigor feedback live in their editor, not just from
|
|
35
|
+
`rigor check` on the command line.
|
|
36
|
+
- A project commits a shared editor config (e.g. `.vscode/`) and you want
|
|
37
|
+
to add Rigor's LSP to it so the whole team gets it.
|
|
38
|
+
|
|
39
|
+
## When NOT to use
|
|
40
|
+
|
|
41
|
+
- Wiring Rigor into CI — that is `rigor-ci-setup`.
|
|
42
|
+
- The project has no Rigor config yet — run `rigor-project-init` first
|
|
43
|
+
(the LSP uses the same `.rigor.yml` discovery as `rigor check`).
|
|
44
|
+
|
|
45
|
+
## The one stable fact
|
|
46
|
+
|
|
47
|
+
Every editor snippet simply launches **`rigor lsp`** (stdio) and needs
|
|
48
|
+
**`rigor` on the editor's `PATH`** — the same executable `rigor check`
|
|
49
|
+
uses. For GUI editors that do not inherit your shell, the `mise` shim
|
|
50
|
+
path is the most reliable channel (see `rigor docs install`, or
|
|
51
|
+
[Installing Rigor](https://github.com/rigortype/rigor/blob/master/docs/install.md)
|
|
52
|
+
on the web). Do **not** add `rigortype` to the project's `Gemfile` — it
|
|
53
|
+
is a tool, not a library.
|
|
54
|
+
|
|
55
|
+
## Procedure
|
|
56
|
+
|
|
57
|
+
### Phase 1 — confirm the analyzer works from the CLI first
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
rigor check <a-file-or-dir>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The LSP shares `rigor check`'s config discovery and analysis. If `check`
|
|
64
|
+
works from the project root, the LSP will too; if it fails, fix that
|
|
65
|
+
first — the editor would only surface the same failure.
|
|
66
|
+
|
|
67
|
+
### Phase 2 — identify the editor
|
|
68
|
+
|
|
69
|
+
Ask the developer which editor they use, or detect it (a committed
|
|
70
|
+
`.vscode/`, a Neovim `init.lua`, `~/.config/helix/`, an Emacs config).
|
|
71
|
+
The manual chapter covers:
|
|
72
|
+
|
|
73
|
+
- **Neovim** (nvim-lspconfig)
|
|
74
|
+
- **VS Code** (generic LSP-client wrapper / minimal extension)
|
|
75
|
+
- **Helix** (`languages.toml`)
|
|
76
|
+
- **Emacs** (Eglot and lsp-mode)
|
|
77
|
+
|
|
78
|
+
### Phase 3 — apply the matching config
|
|
79
|
+
|
|
80
|
+
Open the manual's **Editor wiring** section and apply the snippet for
|
|
81
|
+
the developer's editor verbatim:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
rigor docs editor-integration
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
(or, pre-install, the web copy:
|
|
88
|
+
<https://github.com/rigortype/rigor/blob/master/docs/manual/09-editor-integration.md>)
|
|
89
|
+
|
|
90
|
+
All snippets invoke `rigor lsp` directly. (Only if the project still
|
|
91
|
+
uses a legacy bundler-local install do you swap in
|
|
92
|
+
`bundle exec rigor lsp` — the manual notes this per editor.)
|
|
93
|
+
|
|
94
|
+
If the project commits a shared editor config (e.g. `.vscode/`), add the
|
|
95
|
+
Rigor LSP wiring there and commit it, so every contributor gets the same
|
|
96
|
+
setup rather than configuring it individually.
|
|
97
|
+
|
|
98
|
+
### Phase 4 — verify
|
|
99
|
+
|
|
100
|
+
Open a Ruby file inside a Rigor-configured project and confirm:
|
|
101
|
+
|
|
102
|
+
- diagnostics appear (on save / as you type), and
|
|
103
|
+
- hover over a method or local shows its inferred type.
|
|
104
|
+
|
|
105
|
+
If the server starts but nothing appears, work the manual's
|
|
106
|
+
**Troubleshooting** section (most often: `rigor` not on the editor's
|
|
107
|
+
PATH, or no `.rigor.yml` at the project root). Capture the LSP log with
|
|
108
|
+
`rigor lsp --log=/tmp/rigor-lsp.log` when filing an issue.
|
|
109
|
+
|
|
110
|
+
## Next step
|
|
111
|
+
|
|
112
|
+
Re-run `rigor skill describe` for the next move — with live feedback in
|
|
113
|
+
the editor, raising protection (`rigor-protection-uplift`) or reducing a
|
|
114
|
+
baseline (`rigor-baseline-reduce`) is a tighter loop.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rigor-mcp-setup
|
|
3
|
+
description: |
|
|
4
|
+
Wire Rigor's bundled MCP server (`rigor mcp`) into an AI coding agent (Claude Code, Claude Desktop, Cursor, Cline) so the agent can call Rigor's read-only analysis tools — rigor_check, rigor_type_of, rigor_triage, rigor_coverage, and more — during a session. The per-client config lives in the manual; this skill identifies the client, applies the right one, and verifies the handshake. Triggers: "set up rigor mcp", "give my AI agent Rigor tools", "wire Rigor into Claude Code / Cursor / Cline", "rigor MCP server". NOT for editor LSP integration (use rigor-editor-setup) or CI (use rigor-ci-setup).
|
|
5
|
+
license: MPL-2.0
|
|
6
|
+
metadata:
|
|
7
|
+
version: 0.1.0
|
|
8
|
+
homepage: https://github.com/rigortype/rigor
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Rigor MCP Setup
|
|
12
|
+
|
|
13
|
+
`rigor mcp` is the Model Context Protocol server bundled with the
|
|
14
|
+
`rigortype` gem. It exposes Rigor's analysis as JSON-RPC tool calls over
|
|
15
|
+
stdio, so an AI coding agent can call Rigor directly during a session —
|
|
16
|
+
check types before a refactor, look up the type at a cursor, or triage a
|
|
17
|
+
project's diagnostics as review context. All tools are **read-only**
|
|
18
|
+
(write-side commands like `rigor init` / `sig-gen --write` are
|
|
19
|
+
deliberately excluded — modifying files stays the developer's call).
|
|
20
|
+
|
|
21
|
+
The authoritative, per-client configuration lives in the manual. With
|
|
22
|
+
Rigor installed, read it **offline** with no network round-trip:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
rigor docs mcp-server
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
(Web fallback, only before Rigor is installed:
|
|
29
|
+
**[Rigor MCP Server — AI Agent Integration](https://github.com/rigortype/rigor/blob/master/docs/manual/10-mcp-server.md)**.)
|
|
30
|
+
This skill is the *workflow* around it (identify the client → apply the
|
|
31
|
+
manual's snippet → verify the handshake), so it does not duplicate (and
|
|
32
|
+
cannot stale-out) the config details.
|
|
33
|
+
|
|
34
|
+
## When to use
|
|
35
|
+
|
|
36
|
+
- A developer wants their AI agent to call Rigor's tools mid-session.
|
|
37
|
+
- A project commits a shared MCP config (`.mcp.json`, `.cursor/mcp.json`)
|
|
38
|
+
and you want to add Rigor to it for the whole team.
|
|
39
|
+
|
|
40
|
+
## When NOT to use
|
|
41
|
+
|
|
42
|
+
- Editor (human) integration — that is `rigor-editor-setup` (`rigor lsp`).
|
|
43
|
+
- The project has no Rigor config yet — run `rigor-project-init` first
|
|
44
|
+
(the MCP tools use the same `.rigor.yml` discovery as `rigor check`).
|
|
45
|
+
|
|
46
|
+
## The tools you are wiring in
|
|
47
|
+
|
|
48
|
+
`rigor_check`, `rigor_type_of`, `rigor_triage`, `rigor_annotate`,
|
|
49
|
+
`rigor_sig_gen`, `rigor_explain`, `rigor_coverage` — each the JSON form
|
|
50
|
+
of the matching `rigor` CLI command. See the manual's **Tool reference**
|
|
51
|
+
for inputs and outputs.
|
|
52
|
+
|
|
53
|
+
## The one stable fact
|
|
54
|
+
|
|
55
|
+
Every client config simply launches **`rigor mcp`** (stdio) and needs
|
|
56
|
+
**`rigor` on the agent's `PATH`** — the same executable `rigor check`
|
|
57
|
+
uses. For agents that do not inherit your shell, the `mise` shim path is
|
|
58
|
+
the most reliable channel (see `rigor docs install`, or
|
|
59
|
+
[Installing Rigor](https://github.com/rigortype/rigor/blob/master/docs/install.md)
|
|
60
|
+
on the web). Do **not** add `rigortype` to the project's `Gemfile` — it
|
|
61
|
+
is a tool, not a library.
|
|
62
|
+
|
|
63
|
+
## Procedure
|
|
64
|
+
|
|
65
|
+
### Phase 1 — confirm the analyzer works from the CLI first
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
rigor check <a-file-or-dir>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The MCP tools share `rigor check`'s config discovery. If `check` works
|
|
72
|
+
from the project root, the tools will too.
|
|
73
|
+
|
|
74
|
+
### Phase 2 — identify the client and apply the config
|
|
75
|
+
|
|
76
|
+
Ask the developer which agent they use, or detect a committed config
|
|
77
|
+
(`.mcp.json`, `.cursor/mcp.json`, `.claude/settings.json`). Apply the
|
|
78
|
+
matching snippet from the manual's **Client wiring** section verbatim —
|
|
79
|
+
it covers Claude Desktop, Claude Code CLI, Cursor, Cline, and a generic
|
|
80
|
+
stdio client:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
rigor docs mcp-server
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
(or, pre-install, the web copy:
|
|
87
|
+
<https://github.com/rigortype/rigor/blob/master/docs/manual/10-mcp-server.md>)
|
|
88
|
+
|
|
89
|
+
Each snippet is the same shape — `{"command": "rigor", "args": ["mcp"]}`.
|
|
90
|
+
If the project commits a shared MCP config, add the Rigor entry there and
|
|
91
|
+
commit it so every contributor gets it.
|
|
92
|
+
|
|
93
|
+
**Working-directory gotcha (from the manual's Troubleshooting):** the
|
|
94
|
+
server discovers config from the directory it is launched in. If the
|
|
95
|
+
client starts `rigor mcp` from `$HOME` or a temp dir, no `.rigor.yml` is
|
|
96
|
+
found and tools return an empty set. Pin it with
|
|
97
|
+
`"args": ["mcp", "--config=/abs/path/.rigor.yml"]`, or pass absolute
|
|
98
|
+
`paths` in the tool call.
|
|
99
|
+
|
|
100
|
+
### Phase 3 — verify the handshake
|
|
101
|
+
|
|
102
|
+
Confirm `rigor mcp` answers the MCP `initialize` request:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
echo '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0"}}}' | rigor mcp
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
A JSON `result` with `serverInfo.name: "rigor"` means it works; nothing
|
|
109
|
+
or a shell error means `rigor` is not on the PATH the client uses. Then
|
|
110
|
+
restart the client and confirm the `rigor_*` tools appear in its tool
|
|
111
|
+
palette.
|
|
112
|
+
|
|
113
|
+
## Next step
|
|
114
|
+
|
|
115
|
+
Re-run `rigor skill describe` for the next move — with the agent able to
|
|
116
|
+
call Rigor's tools, raising protection (`rigor-protection-uplift`) or
|
|
117
|
+
reducing a baseline (`rigor-baseline-reduce`) is a tighter loop.
|