rigortype 0.2.6 → 0.2.7

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/docs/manual/02-cli-reference.md +2 -1
  4. data/docs/manual/08-skills.md +21 -0
  5. data/lib/rigor/cli/coverage_command.rb +42 -10
  6. data/lib/rigor/cli/skill_command.rb +52 -1
  7. data/lib/rigor/environment/rbs_loader.rb +28 -0
  8. data/lib/rigor/inference/statement_evaluator.rb +0 -4
  9. data/lib/rigor/sig_gen/generator.rb +25 -0
  10. data/lib/rigor/sig_gen/method_candidate.rb +7 -2
  11. data/lib/rigor/sig_gen/writer.rb +60 -13
  12. data/lib/rigor/version.rb +1 -1
  13. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack.rb +63 -2
  14. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord.rb +2 -3
  15. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +14 -24
  16. data/plugins/rigor-hanami/lib/rigor/plugin/hanami.rb +10 -3
  17. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +33 -76
  18. data/skills/rigor-ask/SKILL.md +21 -1
  19. data/skills/rigor-baseline-reduce/SKILL.md +16 -0
  20. data/skills/rigor-ci-setup/SKILL.md +96 -249
  21. data/skills/rigor-doctor/SKILL.md +39 -49
  22. data/skills/rigor-doctor/references/01-checks.md +52 -0
  23. data/skills/rigor-editor-setup/SKILL.md +14 -0
  24. data/skills/rigor-mcp-setup/SKILL.md +14 -0
  25. data/skills/rigor-monkeypatch-resolve/SKILL.md +15 -0
  26. data/skills/rigor-plugin-author/SKILL.md +16 -0
  27. data/skills/rigor-plugin-review/SKILL.md +174 -0
  28. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +214 -0
  29. data/skills/rigor-plugin-tune/SKILL.md +21 -2
  30. data/skills/rigor-project-init/SKILL.md +16 -0
  31. data/skills/rigor-protection-uplift/SKILL.md +15 -0
  32. data/skills/rigor-rbs-setup/SKILL.md +15 -0
  33. data/skills/rigor-upgrade/SKILL.md +16 -0
  34. metadata +7 -4
@@ -27,6 +27,22 @@ environment.
27
27
  > covers the in-repo layout, `plugin_helpers.rb`, and `make verify`.
28
28
  > This skill is for plugins that live in *your* project.
29
29
 
30
+ ## First: load the version-current copy
31
+
32
+ The plugin contract is pre-1.0 and moving (see the next section), so this
33
+ skill's step detail — in its `references/` files — is exactly the kind that
34
+ drifts between releases. Follow the copy that ships with the **installed**
35
+ Rigor rather than any vendored or frozen copy of this file. Get the complete
36
+ current procedure (body + all references, inline) in one call:
37
+
38
+ ```sh
39
+ rigor skill --full rigor-plugin-author
40
+ ```
41
+
42
+ If you already loaded this skill *via* `rigor skill` you have the current
43
+ copy — just proceed. If the `rigor` command is not available, run
44
+ **`rigor-next-steps`** to install Rigor first, then come back.
45
+
30
46
  ## Important — the plugin contract is a preview (pre-1.0)
31
47
 
32
48
  Rigor's plugin contract (ADR-2) is **not yet frozen**. It stabilises
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: rigor-plugin-review
3
+ description: |
4
+ Review an existing Rigor plugin's source against the current authoring contract and produce a prioritized upgrade path — the modernization counterpart to rigor-plugin-author. Audits config-default declaration (ADR-40), the AST-walk model (node_rule vs a hand-rolled traversal), return-type / narrowing hooks (dynamic_return / narrowing_facts, not the removed flow_contribution_for or deprecated type_specifier), the ADR-60 WD4 authoring helpers (diagnostic / diagnostics_for / suggest / producer_value / read_fact), engine-collaboration vs reimplementation, cache-producer soundness, manifest-field hygiene, and doc freshness. Triggers: "review this Rigor plugin", "does my plugin follow best practices", "upgrade our rigor-prefixed plugin to the latest contract", "modernize this plugin", "is this plugin using the current API". NOT for authoring a new plugin (use rigor-plugin-author), enabling bundled plugins on a project (use rigor-plugin-tune), or tuning plugin config.
5
+ license: MPL-2.0
6
+ metadata:
7
+ version: 0.1.0
8
+ homepage: https://github.com/rigortype/rigor
9
+ ---
10
+
11
+ # Rigor Plugin Review
12
+
13
+ Audit an **existing** Rigor plugin — a bundled one in the rigor
14
+ monorepo (`plugins/` or `examples/`), or your own `rigor-<id>` gem —
15
+ against the current `Rigor::Plugin::Base` authoring contract, and hand
16
+ back a **prioritized upgrade path**. This is the review / upgrade
17
+ counterpart to `rigor-plugin-author` (which creates new plugins).
18
+
19
+ Plugins written before a contract addition keep working — the gate is
20
+ compatibility, not currency — but they drift from the idiom other
21
+ authors copy. The commonest drift, in rough order of how often it
22
+ appears:
23
+
24
+ 1. **Config defaults** declared with a `DEFAULT_*` constant +
25
+ `config.fetch(k, DEFAULT)` instead of `config_schema {kind:,
26
+ default:}` (ADR-40).
27
+ 2. **Hand-rolled boilerplate** the ADR-60 WD4 authoring helpers now
28
+ own — a Levenshtein "did you mean", a `@table`/`@load_error` memo +
29
+ rescue, a `Diagnostic.new` where a node exists.
30
+ 3. **A hand-rolled AST walk** where the engine-owned `node_rule` now
31
+ fits (ADR-37 / ADR-52).
32
+ 4. **Removed / renamed hooks** still named — `flow_contribution_for`
33
+ (deleted, ADR-52 WD3) or `type_specifier` (deprecated alias for
34
+ `narrowing_facts`, ADR-80).
35
+ 5. **Stale docs** — archaeology about deleted hooks, pinned version
36
+ references that no longer mean anything.
37
+
38
+ ## First: load the version-current copy
39
+
40
+ This skill audits against a contract that moves release to release (hook
41
+ renames, new helpers, deprecations), so its checklist — in its
42
+ `references/` files — is only as good as the Rigor it ships with. Follow
43
+ the copy that ships with the **installed** Rigor rather than any vendored
44
+ or frozen copy of this file. Get the complete current procedure (body + all
45
+ references, inline) in one call:
46
+
47
+ ```sh
48
+ rigor skill --full rigor-plugin-review
49
+ ```
50
+
51
+ If you already loaded this skill *via* `rigor skill` you have the current
52
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
53
+ **`rigor-next-steps`** to install Rigor first, then come back.
54
+
55
+ ## When to use / not use
56
+
57
+ **Use it** when someone asks to review a plugin's quality, check it
58
+ against best practices, or upgrade it to the current contract — whether
59
+ it lives in the rigor monorepo or in an external repo.
60
+
61
+ **Do not use it** for:
62
+
63
+ - **Authoring a new plugin** → `rigor-plugin-author`.
64
+ - **Choosing / enabling bundled plugins on a project** →
65
+ `rigor-plugin-tune`.
66
+ - **A behavioural bug in a plugin** — that is ordinary debugging, not a
67
+ contract-conformance pass.
68
+
69
+ ## Read the plugin — and read the contract
70
+
71
+ Rigor is installed on disk, so both the plugin under review and the
72
+ worked-example plugins are readable source:
73
+
74
+ ```sh
75
+ rigor plugin list # every bundled + example plugin, with paths
76
+ rigor plugin print rigor-<id> # a plugin's main source, inline
77
+ rigor plugin path rigor-<id> # its directory, to browse
78
+ ```
79
+
80
+ The **authoritative** authoring surface — the one this review scores
81
+ against — is the internal spec, not this file:
82
+
83
+ - [`docs/internal-spec/plugin.md`](https://github.com/rigortype/rigor/blob/master/docs/internal-spec/plugin.md)
84
+ — manifest, `node_rule` / `node_file_context`, `dynamic_return` /
85
+ `narrowing_facts`, the `#diagnostic` / `#diagnostics_for` / `.suggest`
86
+ / `#read_fact` author helpers, `config_schema` `{kind:, default:}`.
87
+ - [`docs/internal-spec/plugin-cache-producers.md`](https://github.com/rigortype/rigor/blob/master/docs/internal-spec/plugin-cache-producers.md)
88
+ — `producer` / `#cache_for` / `#producer_value` / `#producer_error`,
89
+ ADR-60 WD3 record-and-validate.
90
+ - [`docs/internal-spec/plugin-trust.md`](https://github.com/rigortype/rigor/blob/master/docs/internal-spec/plugin-trust.md)
91
+ — `TrustPolicy` / `IoBoundary`.
92
+
93
+ When the checklist below and the spec disagree, **the spec binds** —
94
+ it tracks the installed `rigor` version; this skill is a snapshot.
95
+
96
+ ## Procedure
97
+
98
+ ### Phase 1 — Inventory
99
+
100
+ Read the plugin's `lib/**/*.rb`, its `README.md`, and its integration /
101
+ unit spec. Note: the `manifest(...)` block, every `config.fetch` /
102
+ `DEFAULT_*` constant, every `Rigor::Analysis::Diagnostic.new`, any
103
+ hand-rolled `levenshtein` / `each_child` walk / cross-plugin `@*_resolved`
104
+ flag, and every mention of `flow_contribution_for` / `type_specifier`.
105
+
106
+ ### Phase 2 — Score against the checklist
107
+
108
+ Walk [`references/01-best-practices-checklist.md`](references/01-best-practices-checklist.md)
109
+ concern by concern. For each finding, record: the smell, the modern
110
+ replacement, the authoritative citation, and — critically — whether the
111
+ change is **mechanical** (byte-identical diagnostics expected) or
112
+ **design-level** (needs judgment / may change behaviour).
113
+
114
+ ### Phase 3 — Establish the oracle BEFORE changing anything
115
+
116
+ The plugin's integration spec is the contract you must preserve. Run it
117
+ green first, so you can prove each later step is a faithful refactor:
118
+
119
+ ```sh
120
+ # external gem:
121
+ bundle exec rspec spec/
122
+ # in the rigor monorepo:
123
+ nix … develop --command bundle exec rspec spec/integration/<plugins|examples>/<id>_plugin_spec.rb
124
+ ```
125
+
126
+ If there is no spec, **write one first** (per `rigor-plugin-author`
127
+ Phase 3) — a modernization with no oracle is a guess.
128
+
129
+ ### Phase 4 — Apply the upgrade path, mechanical first
130
+
131
+ Order the work low-risk → high-risk, and **re-run the spec after every
132
+ step**:
133
+
134
+ 1. **Mechanical (expect byte-identical diagnostics):** ADR-40 config
135
+ defaults · helper swaps (`suggest` / `producer_value` / `diagnostic`
136
+ / `diagnostics_for` / `read_fact`) · manifest-field renames (ADR-60
137
+ WD1/WD2) · doc freshness. A spec that changes here means the swap was
138
+ not faithful — fix it, do not re-baseline.
139
+ 2. **Design-level (may change behaviour — validate empirically):** an
140
+ AST-walk migration onto `node_rule`; an engine-collaboration refactor
141
+ that reads `Scope#type_of` instead of a hand-rolled binding map.
142
+ **Do not delete hand-rolled state before proving the engine gives you
143
+ the same information** — see the `rigor-units` trap in the checklist
144
+ (the diagnostics-side `Scope` is a *seed entry scope* without
145
+ flow-accumulated local bindings, so a cross-statement binding map can
146
+ be necessary, not redundant).
147
+
148
+ ### Phase 5 — Verify
149
+
150
+ ```sh
151
+ rigor check <plugin>/lib # ADR-43 contract self-check — MUST be clean
152
+ rigor plugins --strict # the plugin still loads
153
+ rigor plugins --capabilities # node-rule types / dynamic_return receivers look right
154
+ bundle exec rspec … # the oracle spec, still green
155
+ ```
156
+
157
+ In the **rigor monorepo**, the gate is `make check-plugins` (runs
158
+ `rigor check` over every `plugins/*/lib` + `examples/*/lib`) plus
159
+ `make verify`; land the change as its own commit(s) with the spec as
160
+ the byte-identical gate.
161
+
162
+ ## Output
163
+
164
+ Hand the user a table — smell → replacement → authority → mechanical /
165
+ design — ranked so the mechanical, oracle-gated wins land first, and
166
+ call out any finding (like the units binding-map case) where the
167
+ "obvious" modernization is actually wrong. If nothing is stale, say so
168
+ plainly: a plugin that already tracks the current contract is a pass,
169
+ not an occasion to invent churn.
170
+
171
+ ## Next step
172
+
173
+ Re-run `rigor skill describe` for the next move, or `rigor-plugin-author`
174
+ if the review surfaced a *new* capability the plugin should grow.
@@ -0,0 +1,214 @@
1
+ # Plugin best-practices checklist
2
+
3
+ Score a plugin concern by concern. Each row is **smell → modern
4
+ replacement → authority**. The authority column names the binding
5
+ surface (`docs/internal-spec/*` or the ADR); when it disagrees with
6
+ this file, it wins.
7
+
8
+ `M` = mechanical (byte-identical diagnostics expected; oracle-gated).
9
+ `D` = design-level (may change behaviour; validate empirically).
10
+
11
+ ---
12
+
13
+ ## 1. Manifest & config defaults (ADR-40) — `M`
14
+
15
+ **Smell:**
16
+
17
+ ```ruby
18
+ DEFAULT_ROUTES_FILE = "config/routes.yml"
19
+ config_schema: { "routes_file" => :string }
20
+ # …
21
+ @routes_file = config.fetch("routes_file", DEFAULT_ROUTES_FILE)
22
+ ```
23
+
24
+ **Modern:**
25
+
26
+ ```ruby
27
+ config_schema: { "routes_file" => { kind: :string, default: "config/routes.yml" } }
28
+ # …
29
+ @routes_file = config["routes_file"] # default merged under user config
30
+ ```
31
+
32
+ `Base#config` merges `manifest.config_defaults` beneath the user config,
33
+ so the plugin reads the key directly and the `DEFAULT_*` constant goes
34
+ away. Keep a constant only where a value needs *validation the merged
35
+ default cannot express* (e.g. an allow-listed `severity` that must fall
36
+ back when a user supplies a bad value).
37
+
38
+ **Authority:** `docs/internal-spec/plugin.md` § "Declared config
39
+ defaults — `config_schema` `{ kind:, default: }`".
40
+
41
+ ---
42
+
43
+ ## 2. AST-walk ownership (ADR-37 / ADR-52) — `D`
44
+
45
+ **Smell:** a hand-rolled traversal for per-node checks —
46
+ `root.compact_child_nodes.each { … }`, a bespoke `Walker` that recurses
47
+ the tree, or a `#diagnostics_for_file` that re-walks to find call sites.
48
+
49
+ **Modern:** declare `node_rule(Prism::CallNode) { |node, scope, path| … }`
50
+ and let the engine own the single per-file walk. For a two-pass
51
+ (collect-then-validate) plugin, add `node_file_context { |root, scope| … }`
52
+ — it runs once before the node rules and threads a file-local value in
53
+ as the rule block's fourth argument.
54
+
55
+ **Keep `#diagnostics_for_file`** only for genuinely whole-file
56
+ diagnostics a per-node walk cannot express — see concern 5 for the case
57
+ where a stateful whole-file walk is *required*, not lazy.
58
+
59
+ **"Genuinely whole-file" is a sharp line — apply it, don't defer to
60
+ precedent.** A per-*class* or per-*def* contract check (does this class
61
+ define `#get`? does its body return the contracted type?) IS
62
+ node-expressible — migrate it to `node_rule(Prism::ClassNode)` /
63
+ `node_rule(Prism::DefNode)`, even if a shipped production plugin still
64
+ uses `#diagnostics_for_file` + a hand-rolled `class_nodes` walk for the
65
+ same job (`rigor-hanami`'s ADR-28 check half does — an equivalent,
66
+ older shape, not a reason to keep a new copy hand-rolled). The genuine
67
+ whole-file case is a diagnostic whose *identity or count is not tied to
68
+ any one node* — e.g. `rigor-routes`'s "routes file failed to load"
69
+ warning, which must fire exactly once per file (or run) even on a file
70
+ with zero matching nodes. That cannot be a node rule; a per-class check
71
+ can.
72
+
73
+ **Authority:** `docs/internal-spec/plugin.md` §§ "Node-scoped rules —
74
+ `node_rule`", "`node_file_context`".
75
+
76
+ ---
77
+
78
+ ## 3. Return-type & narrowing hooks (ADR-37 / ADR-52 / ADR-80) — `M`/`D`
79
+
80
+ **Smell:** `flow_contribution_for` (deleted in ADR-52 WD3 — *defining it
81
+ now raises `ArgumentError`*), or `type_specifier` (the pre-ADR-80 name).
82
+
83
+ **Modern:** `dynamic_return(receivers:/methods:/file_methods:)` to
84
+ *supply* a return type, `narrowing_facts(methods:)` to supply
85
+ post-return narrowing facts. `type_specifier` survives as a
86
+ deprecating alias removed in 0.3.0 — rename to `narrowing_facts`.
87
+
88
+ The gate resolves after `#init` when passed a callable
89
+ (`methods: -> { [@method_name] }`), so config-derived method names work.
90
+
91
+ **Authority:** `docs/internal-spec/plugin.md` § "Return-type and
92
+ narrowing contributions". `M` for the pure rename; `D` if you are adding
93
+ a contribution the plugin did not have.
94
+
95
+ ---
96
+
97
+ ## 4. Authoring helpers (ADR-37 / ADR-60 WD4) — `M`
98
+
99
+ The single richest source of drift. Each helper replaces a hand-rolled
100
+ shape and is expected to be diagnostics-preserving.
101
+
102
+ | Smell | Modern | Authority |
103
+ | --- | --- | --- |
104
+ | `Rigor::Analysis::Diagnostic.new(line:, column: loc.start_column + 1, …)` where a node exists | `#diagnostic(node, path:, message:, severity:, rule:)` (or `location: node.message_loc` for a sub-span) | plugin.md § "Positioning a diagnostic — `#diagnostic`" |
105
+ | `violations.map { |v| diagnostic(node, message: v.message, …) }` | `#diagnostics_for(violations, path:, node:)` — duck-types `#message` / `#node` / `#severity` / `#rule` / `#location` | plugin.md § author helpers (ADR-60 WD4) |
106
+ | A hand-rolled `levenshtein` / `closest_*` "did you mean" | `Rigor::Plugin::Base.suggest(name, candidates)` (`DidYouMean::SpellChecker`) — a **class** method, callable from an `Analyzer` too | plugin.md § "`Base.suggest`" |
107
+ | `@table ||= cache_for(id).call` + a multi-`rescue` ladder + an `@load_error` ivar | `#producer_value(id, params:)` (memoised incl. nil) + `#producer_error(id)` (the rescued exception, for a tailored message) | plugin-cache-producers.md § "Invalidation contract" |
108
+ | `@x_resolved` flag guarding `services.fact_store.read` | `#read_fact(plugin_id:, name:)` — nil-inclusive memo, retires the flag | plugin.md § author helpers (ADR-60 WD4) |
109
+ | Hand-parsing a `Prism::SymbolNode#value` / string literal | `Rigor::Source::Literals` | plugin.md § "Extracting argument literals" |
110
+ | A private reimplementation of a target library (own inflector, own pure helper) | Call the library's safe methods directly — `Plugin::Inflector` over real `ActiveSupport::Inflector` (ADR-39) | plugin.md § "Target-library invocation" |
111
+
112
+ **Note on tailored load-error messages:** `#producer_value` rescues
113
+ every `StandardError` into `#producer_error`, so a plugin that wants
114
+ class-specific messages ("not found" vs "failed to parse" vs
115
+ access-denied) switches on `producer_error(id)`'s class when building
116
+ the load-error diagnostic — cleaner than an inline rescue ladder and
117
+ still message-preserving. A *file-level* load-error (line 1, no node)
118
+ legitimately keeps a direct `Diagnostic.new` — `#diagnostic` needs a
119
+ node to position at.
120
+
121
+ ---
122
+
123
+ ## 5. Engine collaboration vs reimplementation — `D` (read the trap)
124
+
125
+ **Principle (rigor-pattern):** do not re-implement a fact the engine
126
+ already computes. If you need "is this a literal string?" / "what type
127
+ did inference give this expression?", read `Scope#type_of(node)` rather
128
+ than tracking it yourself. `rigor-pattern` reads the engine's
129
+ `LiteralStringFolding` result back instead of propagating strings by
130
+ hand.
131
+
132
+ **The trap (rigor-units) — when a hand-rolled binding map is NOT
133
+ redundant:** the `Scope` handed to the **diagnostics** side
134
+ (`#diagnostics_for_file` / a `node_rule`) is the **seed entry scope**.
135
+ `Scope#type_of` re-evaluates a *self-contained* expression on demand
136
+ (`scope.type_of(100.kilometers)` folds through the plugin's own
137
+ `dynamic_return`), but it carries **no flow-accumulated local
138
+ bindings**: for `speed = distance / time`, `scope.type_of(distance)` is
139
+ `untyped`, because the entry scope never bound the earlier assignment.
140
+ Only the **flow scope** handed to a `dynamic_return` block resolves such
141
+ locals. So a diagnostics-side check that must follow a dimension /
142
+ type across statements legitimately keeps its own single-pass binding
143
+ map — deleting it and reaching for `scope.type_of` collapses
144
+ cross-statement propagation.
145
+
146
+ **How to tell which case you are in:** if the value you need lives *at
147
+ the call site you are inspecting* (a literal argument, a self-contained
148
+ sub-expression) → read `Scope#type_of`. If it lives *in an earlier
149
+ statement's local binding* and you are on the diagnostics side → the
150
+ engine will not hand it to you; keep the binding map, and document why.
151
+ **Validate empirically before deleting state:** run the integration
152
+ spec after the change; a wave of failures on multi-statement fixtures is
153
+ this trap.
154
+
155
+ **Authority:** the reasoning is recorded in
156
+ `docs/notes/20260704-examples-plugin-modernization-survey.md` (the
157
+ `rigor-units` section) and the `rigor-units` class comment itself.
158
+
159
+ ---
160
+
161
+ ## 6. Cache producers (ADR-60 WD3) — `M`/`D`
162
+
163
+ **Smell:** a "prime the read before `cache_for` so the digest is
164
+ captured" comment, or a producer that globs a directory but does not
165
+ declare `watch:`.
166
+
167
+ **Modern:** record-and-validate — the `io_boundary.read_file` inside the
168
+ `producer` block is captured into the dependency descriptor *after* the
169
+ block runs, so there is nothing to prime. A producer that reads a *set*
170
+ of files by glob declares `watch:` so file *additions* invalidate too.
171
+
172
+ **Authority:** `docs/internal-spec/plugin-cache-producers.md` §§
173
+ "Invalidation contract", "`producer(... watch:)`".
174
+
175
+ ---
176
+
177
+ ## 7. Manifest-field hygiene (ADR-60 WD1 / WD2) — `M`
178
+
179
+ **Smell:** `external_files:` (never wired — removed in ADR-60 WD1);
180
+ `BlockAsMethod verbs:` (renamed → `method_names:`); `NestedClassTemplate
181
+ name_arg_position:` (renamed → `symbol_arg_position:`).
182
+
183
+ **Modern:** drop `external_files:`; use the renamed keys.
184
+
185
+ **Authority:** `docs/internal-spec/plugin.md` § "`Rigor::Plugin::Manifest`"
186
+ and `macro-substrate.md`.
187
+
188
+ ---
189
+
190
+ ## 8. Documentation freshness — `M`
191
+
192
+ **Smell:** "the former `flow_contribution_for` hook was removed"
193
+ archaeology in a README / class comment (a reader who never knew the
194
+ deleted hook does not need it named); pinned version references that no
195
+ longer carry meaning ("introduced in v0.0.9").
196
+
197
+ **Modern:** describe the *current* mechanism directly. Keep a historical
198
+ note only where a reader migrating an old plugin genuinely needs it —
199
+ and put that in a CHANGELOG / migration note, not the class docstring.
200
+
201
+ ---
202
+
203
+ ## 9. Verification (ADR-43) — always
204
+
205
+ - `rigor check <plugin>/lib` — the ADR-43 contract self-check resolves
206
+ the plugin's inherited `Plugin::Base` calls and warns on contract
207
+ misuse. MUST be clean; fix the cause, never disable the rule.
208
+ - `rigor plugins --strict` — the plugin still activates.
209
+ - `rigor plugins --capabilities` — `node_rule_types` /
210
+ `dynamic_return_receivers` / `type_specifier_methods` reflect the
211
+ declarations.
212
+ - The integration / unit spec — green, and byte-identical across every
213
+ mechanical step.
214
+ - In the monorepo: `make check-plugins` + `make verify`.
@@ -20,6 +20,21 @@ All `rigor-*` plugins ship **bundled inside the `rigortype` gem** — no
20
20
  separate install. Enabling one is just adding its id to `plugins:` in
21
21
  `.rigor.dist.yml`.
22
22
 
23
+ ## First: load the version-current copy
24
+
25
+ This skill's exact commands, flags, and config keys drift between Rigor
26
+ releases, so follow the copy that ships with the **installed** Rigor rather
27
+ than any vendored or frozen copy of this file. Get the complete current
28
+ procedure in one call:
29
+
30
+ ```sh
31
+ rigor skill --full rigor-plugin-tune
32
+ ```
33
+
34
+ If you already loaded this skill *via* `rigor skill` you have the current
35
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
36
+ **`rigor-next-steps`** to install Rigor first, then come back.
37
+
23
38
  ## When to use
24
39
 
25
40
  - The project added (or removed) a gem since it was onboarded.
@@ -43,9 +58,13 @@ dependencies in `Gemfile.lock`.
43
58
  ### Phase 2 — match against the bundled catalogue
44
59
 
45
60
  The authoritative, current list of bundled plugins (the count drifts as
46
- new ones land) is the catalogue:
61
+ new ones land) comes from the **installed** Rigor itself — read it there,
62
+ not from a web page that may describe a different version:
47
63
 
48
- <https://github.com/rigortype/rigor/blob/master/plugins/README.md>
64
+ ```sh
65
+ rigor docs manual/plugins/README # the catalogue of every bundled plugin, offline
66
+ rigor plugins # what is enabled in THIS project right now
67
+ ```
49
68
 
50
69
  For each Gemfile.lock dependency, check whether a bundled `rigor-<gem>`
51
70
  plugin exists and is **not** already in `plugins:`. Common matches:
@@ -23,6 +23,22 @@ chapter for the install channels (`mise` recommended). This skill
23
23
  references only public CLI flags and config keys — the same surface
24
24
  `rigor --help` documents.
25
25
 
26
+ ## First: load the version-current copy
27
+
28
+ This skill's step detail lives in its `references/` files, and its exact
29
+ commands, flags, and config keys drift between Rigor releases — so follow
30
+ the copy that ships with the **installed** Rigor rather than any vendored
31
+ or frozen copy of this file. Get the complete current procedure (body + all
32
+ references, inline) in one call:
33
+
34
+ ```sh
35
+ rigor skill --full rigor-project-init
36
+ ```
37
+
38
+ If you already loaded this skill *via* `rigor skill` you have the current
39
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
40
+ **`rigor-next-steps`** to install Rigor first, then come back.
41
+
26
42
  ## Phase 0 — When to use this skill
27
43
 
28
44
  Trigger when the user says "set up Rigor here", "configure rigor for
@@ -16,6 +16,21 @@ type. This skill *acts* on that surfacing under the discipline that keeps
16
16
  Rigor false-positive-safe: protection goes up, and not one line of
17
17
  working code starts reporting a new diagnostic.
18
18
 
19
+ ## First: load the version-current copy
20
+
21
+ This skill's exact commands, flags, carrier syntax, and rule ids drift
22
+ between Rigor releases, so follow the copy that ships with the **installed**
23
+ Rigor rather than any vendored or frozen copy of this file. Get the
24
+ complete current procedure in one call:
25
+
26
+ ```sh
27
+ rigor skill --full rigor-protection-uplift
28
+ ```
29
+
30
+ If you already loaded this skill *via* `rigor skill` you have the current
31
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
32
+ **`rigor-next-steps`** to install Rigor first, then come back.
33
+
19
34
  ## When to use
20
35
 
21
36
  - A user wants to raise how much of their code Rigor can actually catch
@@ -18,6 +18,21 @@ community RBS collection at
18
18
  [`ruby/gem_rbs_collection`](https://github.com/ruby/gem_rbs_collection);
19
19
  this skill wires it into the project.
20
20
 
21
+ ## First: load the version-current copy
22
+
23
+ This skill's exact commands, flags, and config keys drift between Rigor
24
+ releases, so follow the copy that ships with the **installed** Rigor rather
25
+ than any vendored or frozen copy of this file. Get the complete current
26
+ procedure in one call:
27
+
28
+ ```sh
29
+ rigor skill --full rigor-rbs-setup
30
+ ```
31
+
32
+ If you already loaded this skill *via* `rigor skill` you have the current
33
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
34
+ **`rigor-next-steps`** to install Rigor first, then come back.
35
+
21
36
  ## When to use
22
37
 
23
38
  - `rigor check` ends with `info: N gem(s) in Gemfile.lock have no RBS
@@ -17,6 +17,22 @@ sharpness exposes. This skill adopts the upgrade without either blindly
17
17
  regenerating the baseline (which buries genuine new catches) or treating
18
18
  every new line as a regression.
19
19
 
20
+ ## First: load the version-current copy
21
+
22
+ This skill's exact commands, flags, and config keys drift between Rigor
23
+ releases, so follow the copy that ships with the **installed** Rigor rather
24
+ than any vendored or frozen copy of this file — doubly so here, since you
25
+ just changed the version this skill is meant to track. Get the complete
26
+ current procedure in one call:
27
+
28
+ ```sh
29
+ rigor skill --full rigor-upgrade
30
+ ```
31
+
32
+ If you already loaded this skill *via* `rigor skill` you have the current
33
+ copy — just proceed. If `rigor` is not on `PATH`, this task needs it: run
34
+ **`rigor-next-steps`** to install Rigor first, then come back.
35
+
20
36
  ## When to use
21
37
 
22
38
  - You just ran `mise use gem:rigortype` / `gem update rigortype` and want
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 1980-01-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: language_server-protocol
@@ -886,6 +886,7 @@ files:
886
886
  - skills/rigor-baseline-reduce/references/02-fix-or-suppress.md
887
887
  - skills/rigor-ci-setup/SKILL.md
888
888
  - skills/rigor-doctor/SKILL.md
889
+ - skills/rigor-doctor/references/01-checks.md
889
890
  - skills/rigor-editor-setup/SKILL.md
890
891
  - skills/rigor-mcp-setup/SKILL.md
891
892
  - skills/rigor-monkeypatch-resolve/SKILL.md
@@ -894,6 +895,8 @@ files:
894
895
  - skills/rigor-plugin-author/references/01-plan-and-scaffold.md
895
896
  - skills/rigor-plugin-author/references/02-walker-and-types.md
896
897
  - skills/rigor-plugin-author/references/03-test-and-ship.md
898
+ - skills/rigor-plugin-review/SKILL.md
899
+ - skills/rigor-plugin-review/references/01-best-practices-checklist.md
897
900
  - skills/rigor-plugin-tune/SKILL.md
898
901
  - skills/rigor-project-init/SKILL.md
899
902
  - skills/rigor-project-init/references/01-detect.md
@@ -909,7 +912,7 @@ licenses:
909
912
  metadata:
910
913
  bug_tracker_uri: https://github.com/rigortype/rigor/issues
911
914
  source_code_uri: https://github.com/rigortype/rigor
912
- documentation_uri: https://github.com/rigortype/rigor/tree/main/docs
915
+ documentation_uri: https://github.com/rigortype/rigor/tree/master/docs
913
916
  rubygems_mfa_required: 'true'
914
917
  rdoc_options: []
915
918
  require_paths:
@@ -958,7 +961,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
958
961
  - !ruby/object:Gem::Version
959
962
  version: '0'
960
963
  requirements: []
961
- rubygems_version: 4.0.10
964
+ rubygems_version: 3.7.2
962
965
  specification_version: 4
963
966
  summary: Inference-first static analysis for Ruby.
964
967
  test_files: []