rigortype 0.2.1 → 0.2.2
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 +557 -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 +532 -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.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/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
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Running Rigor in CI
|
|
2
|
+
|
|
3
|
+
Rigor runs on Ruby 4.0 (see
|
|
4
|
+
[Installing Rigor](01-installation.md)). In CI that
|
|
5
|
+
has one consequence worth stating up front; the rest of this page
|
|
6
|
+
follows from it.
|
|
7
|
+
|
|
8
|
+
## Run Rigor in its own job
|
|
9
|
+
|
|
10
|
+
Run Rigor in a **separate CI job** from your test suite — better
|
|
11
|
+
still, a separate workflow file. The reason is concrete:
|
|
12
|
+
`ruby/setup-ruby` sets the *job's* active Ruby. A test job
|
|
13
|
+
provisions the Ruby your project runs (often a 3.x version, or a
|
|
14
|
+
matrix of several); Rigor needs Ruby 4.0. The two cannot share a job
|
|
15
|
+
without the second `setup-ruby` call clobbering the first.
|
|
16
|
+
|
|
17
|
+
A separate job gives Rigor a clean runner where provisioning Ruby
|
|
18
|
+
4.0 conflicts with nothing. A separate workflow file additionally
|
|
19
|
+
gets its own triggers, concurrency group, and status badge — and
|
|
20
|
+
keeps the analyser out of the test workflow, which is good practice
|
|
21
|
+
regardless.
|
|
22
|
+
|
|
23
|
+
## A minimal GitHub Actions workflow
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
# .github/workflows/rigor.yml
|
|
27
|
+
name: rigor
|
|
28
|
+
on: [push, pull_request]
|
|
29
|
+
jobs:
|
|
30
|
+
rigor:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: ruby/setup-ruby@v1
|
|
35
|
+
with:
|
|
36
|
+
ruby-version: "4.0"
|
|
37
|
+
- run: gem install rigortype
|
|
38
|
+
- run: rigor check
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Those four steps check out the project, provision Ruby 4.0, install
|
|
42
|
+
Rigor, and run it. That workflow surfaces diagnostics only in the job
|
|
43
|
+
log. To put them **inline on the changed code** (a PR annotation, a
|
|
44
|
+
code-scanning alert, a merge-request widget) use one of the CI-native
|
|
45
|
+
output formats below.
|
|
46
|
+
|
|
47
|
+
## It already works on GitHub Actions (auto-detection)
|
|
48
|
+
|
|
49
|
+
`rigor check` detects the CI it runs in and, on its default output, surfaces
|
|
50
|
+
diagnostics the platform-native way **without any `--format`** — modelled on
|
|
51
|
+
PHPStan's CI auto-detection. So the minimal workflow at the top of this page
|
|
52
|
+
already produces inline PR annotations on GitHub Actions: the human log stays,
|
|
53
|
+
and `::error` annotations are added on top.
|
|
54
|
+
|
|
55
|
+
- **GitHub Actions** and **TeamCity** (first-class): native annotations are
|
|
56
|
+
emitted on top of the text output automatically.
|
|
57
|
+
- **GitLab CI** (native, but artifact-based): a one-line hint reminds you to
|
|
58
|
+
run `--format gitlab` and publish the `codequality` artifact (below).
|
|
59
|
+
- **Other CIs** (CircleCI, Jenkins, Travis, Azure, Bitbucket, Buildkite,
|
|
60
|
+
Drone, …): a one-line hint points you at the reviewdog or `--format junit`
|
|
61
|
+
path.
|
|
62
|
+
|
|
63
|
+
Auto-detection only augments the default human output — an explicit
|
|
64
|
+
`--format` is never touched. Turn it off with `--no-ci-detect` or
|
|
65
|
+
`RIGOR_CI_DETECT=0`. The sections below are for when you want a *specific*
|
|
66
|
+
surface (code scanning, the GitLab widget, review comments) rather than the
|
|
67
|
+
auto default.
|
|
68
|
+
|
|
69
|
+
## Surfacing diagnostics inline in the PR / MR
|
|
70
|
+
|
|
71
|
+
`rigor check --format` renders the same diagnostics in a format your CI
|
|
72
|
+
platform reads to annotate the diff directly, instead of leaving them in
|
|
73
|
+
the job log ([ADR-51](../adr/51-ci-diagnostic-output-formats.md)). These
|
|
74
|
+
layer on the generic `--format json` stream; they add no new diagnostics,
|
|
75
|
+
only a platform-native rendering. Ready-to-copy template files live under
|
|
76
|
+
[`ci-templates/`](ci-templates/).
|
|
77
|
+
|
|
78
|
+
### GitHub — inline annotations (the default)
|
|
79
|
+
|
|
80
|
+
`--format github` emits GitHub Actions workflow commands
|
|
81
|
+
(`::error file=…,line=…::`) that the runner turns into inline annotations
|
|
82
|
+
on the PR — no upload step, no code-scanning setup, no extra permissions.
|
|
83
|
+
Because it works on **every** repository (public or private, no paid
|
|
84
|
+
features), it is the recommended default for GitHub:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
- run: gem install rigortype
|
|
88
|
+
- run: rigor check --format github
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### GitHub — code scanning (SARIF)
|
|
92
|
+
|
|
93
|
+
Upgrade to SARIF for the Security tab, deduped + persistent alerts, and
|
|
94
|
+
richer PR alerts — **when code scanning is available**: a public repo
|
|
95
|
+
(free), or a private repo with GitHub Advanced Security / Code Security
|
|
96
|
+
enabled. (Without it, `upload-sarif` fails with *"GitHub Advanced Security
|
|
97
|
+
must be enabled for this repository"* — use the annotations form above.)
|
|
98
|
+
The check step uses `continue-on-error` (and the upload runs `if: always()`)
|
|
99
|
+
so a non-zero Rigor exit still publishes the report:
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
# .github/workflows/rigor.yml
|
|
103
|
+
name: rigor
|
|
104
|
+
on: [push, pull_request]
|
|
105
|
+
permissions:
|
|
106
|
+
contents: read
|
|
107
|
+
security-events: write # required by upload-sarif
|
|
108
|
+
jobs:
|
|
109
|
+
rigor:
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/checkout@v4
|
|
113
|
+
- uses: ruby/setup-ruby@v1
|
|
114
|
+
with:
|
|
115
|
+
ruby-version: "4.0"
|
|
116
|
+
- run: gem install rigortype
|
|
117
|
+
- run: rigor check --format sarif > rigor.sarif
|
|
118
|
+
continue-on-error: true
|
|
119
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
120
|
+
if: always()
|
|
121
|
+
with:
|
|
122
|
+
sarif_file: rigor.sarif
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
SARIF is the cross-platform option: the same report is consumed by any
|
|
126
|
+
SARIF-aware tool, not only GitHub.
|
|
127
|
+
|
|
128
|
+
### GitLab — Code Quality widget
|
|
129
|
+
|
|
130
|
+
`--format gitlab` emits a GitLab Code Quality (CodeClimate-subset) report.
|
|
131
|
+
Publish it as a `codequality` report artifact and GitLab renders the
|
|
132
|
+
findings in the merge-request widget:
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
# .gitlab-ci.yml
|
|
136
|
+
rigor:
|
|
137
|
+
image: ruby:4.0
|
|
138
|
+
script:
|
|
139
|
+
- gem install rigortype
|
|
140
|
+
- rigor check --format gitlab > gl-code-quality-report.json
|
|
141
|
+
artifacts:
|
|
142
|
+
reports:
|
|
143
|
+
codequality: gl-code-quality-report.json
|
|
144
|
+
when: always
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Any platform — reviewdog
|
|
148
|
+
|
|
149
|
+
[reviewdog](https://github.com/reviewdog/reviewdog) posts findings as PR/MR
|
|
150
|
+
review comments on GitHub, GitLab, Gerrit, Bitbucket, and Gitea. It reads
|
|
151
|
+
Rigor's `sarif` or `checkstyle` output, so one of those formats reaches
|
|
152
|
+
*all* of its reporters. Install it with
|
|
153
|
+
[`reviewdog/action-setup`](https://github.com/reviewdog/action-setup) and
|
|
154
|
+
pipe Rigor into it:
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
- uses: reviewdog/action-setup@v1
|
|
158
|
+
- run: rigor check --format checkstyle | reviewdog -f=checkstyle -reporter=github-pr-review -fail-level=error
|
|
159
|
+
env:
|
|
160
|
+
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`github-pr-review` needs `permissions: pull-requests: write`. The
|
|
164
|
+
`rigor-ci-setup` skill (`rigor skill rigor-ci-setup`) walks through
|
|
165
|
+
the reporter and `-fail-level` choices.
|
|
166
|
+
|
|
167
|
+
### Other test-report CI — JUnit
|
|
168
|
+
|
|
169
|
+
`--format junit` emits JUnit XML, which GitHub test reporting, GitLab,
|
|
170
|
+
CircleCI, and Jenkins render. Every diagnostic becomes a `testcase` with a
|
|
171
|
+
`failure` typed by its severity:
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
rigor check --format junit > rigor-junit.xml
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Severity mapping
|
|
178
|
+
|
|
179
|
+
Rigor's severities map per format ([ADR-51](../adr/51-ci-diagnostic-output-formats.md) WD2):
|
|
180
|
+
|
|
181
|
+
| Rigor | SARIF | GitHub | GitLab | Checkstyle | JUnit | TeamCity |
|
|
182
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
183
|
+
| error | `error` | `::error` | `major` | `error` | `error` | `ERROR` |
|
|
184
|
+
| warning | `warning` | `::warning` | `minor` | `warning` | `warning` | `WARNING` |
|
|
185
|
+
| info | `note` | `::notice` | `info` | `info` | `info` | `INFO` |
|
|
186
|
+
|
|
187
|
+
The exit code is unchanged by `--format` — `0` when there are no errors,
|
|
188
|
+
`1` otherwise — so the job still gates the pipeline. `--format json`
|
|
189
|
+
remains available for any other tool that wants the raw diagnostic stream.
|
|
190
|
+
|
|
191
|
+
## Pinning Rigor's version
|
|
192
|
+
|
|
193
|
+
The workflow above installs whatever `rigortype` is current at run
|
|
194
|
+
time. To pin a version — and keep CI reproducible — choose one of the
|
|
195
|
+
options below. While the `0.1.x` line is in preview the surface is
|
|
196
|
+
still settling, so pinning is recommended; what Rigor commits to
|
|
197
|
+
keeping stable (and from which release) is enumerated in
|
|
198
|
+
[`docs/compatibility.md`](../compatibility.md).
|
|
199
|
+
|
|
200
|
+
### A CI-only `Gemfile` (recommended)
|
|
201
|
+
|
|
202
|
+
Commit a two-line `.github/rigor/Gemfile`:
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
source "https://rubygems.org"
|
|
206
|
+
gem "rigortype", "~> 0.1"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
plus its `Gemfile.lock`, and point the Rigor job at it through
|
|
210
|
+
`BUNDLE_GEMFILE`:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
jobs:
|
|
214
|
+
rigor:
|
|
215
|
+
runs-on: ubuntu-latest
|
|
216
|
+
env:
|
|
217
|
+
BUNDLE_GEMFILE: .github/rigor/Gemfile
|
|
218
|
+
steps:
|
|
219
|
+
- uses: actions/checkout@v4
|
|
220
|
+
- uses: ruby/setup-ruby@v1
|
|
221
|
+
with:
|
|
222
|
+
ruby-version: "4.0"
|
|
223
|
+
bundler-cache: true
|
|
224
|
+
- run: bundle exec rigor check
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
This `Gemfile` is read only by the Rigor job — it never enters your
|
|
228
|
+
application's dependency resolution, and the committed lockfile
|
|
229
|
+
pins Rigor and its dependencies for a reproducible run. Because it
|
|
230
|
+
is an ordinary Bundler `Gemfile`, Dependabot can keep it current:
|
|
231
|
+
add a `bundler` entry scoped to its directory in
|
|
232
|
+
`.github/dependabot.yml`:
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
version: 2
|
|
236
|
+
updates:
|
|
237
|
+
- package-ecosystem: bundler
|
|
238
|
+
directory: /.github/rigor
|
|
239
|
+
schedule:
|
|
240
|
+
interval: weekly
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### A pinned `gem install`
|
|
244
|
+
|
|
245
|
+
`gem install rigortype -v "0.1.15"` in the workflow. Simpler, with no
|
|
246
|
+
extra files — but Dependabot does not see a version inside a `run:`
|
|
247
|
+
step, so updates to the pin are manual.
|
|
248
|
+
|
|
249
|
+
## Container image
|
|
250
|
+
|
|
251
|
+
A standalone image is published to GHCR with Ruby 4.0 and Rigor
|
|
252
|
+
baked in. It suits CI runners with no Ruby toolchain — mount the
|
|
253
|
+
project on `/src`:
|
|
254
|
+
|
|
255
|
+
```sh
|
|
256
|
+
docker run --rm -v "$PWD:/src" ghcr.io/rigortype/rigor check
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`rigor` is the image entrypoint, so subcommands and flags follow the
|
|
260
|
+
image name. Pin a version with an explicit tag —
|
|
261
|
+
`ghcr.io/rigortype/rigor:0.1.15`.
|
|
262
|
+
|
|
263
|
+
## Nix
|
|
264
|
+
|
|
265
|
+
For CI that already runs Nix, the flake exposes Rigor as a package
|
|
266
|
+
with Ruby 4.0 in its closure — a fully hermetic run with nothing
|
|
267
|
+
else on the runner:
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
nix run github:rigortype/rigor#rigor -- check
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
See [ADR-27](../adr/27-tool-distribution-model.md) for the
|
|
274
|
+
distribution model behind this page.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Caching
|
|
2
|
+
|
|
3
|
+
Rigor caches expensive intermediate results — parsed RBS
|
|
4
|
+
environments, per-file analysis products — so a second run
|
|
5
|
+
over an unchanged project is fast. The cache is correct by
|
|
6
|
+
construction: you should never need to clear it to fix a stale
|
|
7
|
+
result. This page is for the times you are curious where it
|
|
8
|
+
lives or want to reclaim the space.
|
|
9
|
+
|
|
10
|
+
## Where it lives
|
|
11
|
+
|
|
12
|
+
The cache is an on-disk directory, `.rigor/cache` by default,
|
|
13
|
+
relative to the project root. Change it with the `cache.path`
|
|
14
|
+
config key:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
cache:
|
|
18
|
+
path: tmp/rigor-cache
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Add the cache directory to your `.gitignore`.
|
|
22
|
+
|
|
23
|
+
## What invalidates an entry
|
|
24
|
+
|
|
25
|
+
Each entry is keyed by a hash of everything its result depends
|
|
26
|
+
on:
|
|
27
|
+
|
|
28
|
+
- the **content** of the source and `.rbs` files that fed it,
|
|
29
|
+
- the **gems** in play, by name and locked version,
|
|
30
|
+
- the active **plugins**, by ID and version,
|
|
31
|
+
- the relevant **configuration**.
|
|
32
|
+
|
|
33
|
+
Change any of those and the dependent entries are recomputed
|
|
34
|
+
automatically. A corrupt or unreadable entry is treated as a
|
|
35
|
+
miss and overwritten — bad cache state cannot wedge a run.
|
|
36
|
+
|
|
37
|
+
The cache is also schema-versioned: after a Rigor upgrade that
|
|
38
|
+
changes the cache format, the stale cache is purged on the
|
|
39
|
+
first writable run.
|
|
40
|
+
|
|
41
|
+
## Controlling the cache
|
|
42
|
+
|
|
43
|
+
| Flag | Effect |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `rigor check --no-cache` | Run without reading or writing the persistent cache. |
|
|
46
|
+
| `rigor check --clear-cache` | Delete the cache directory, then run. |
|
|
47
|
+
| `rigor check --cache-stats` | Print the on-disk cache inventory when the run finishes. |
|
|
48
|
+
| `rigor check --incremental` | Re-analyse only what changed; serve the rest from the incremental snapshot (see below). |
|
|
49
|
+
|
|
50
|
+
There is no config key to disable caching permanently — the
|
|
51
|
+
flags are per-run toggles. To run without a persistent cache
|
|
52
|
+
habitually, point `cache.path` at a disposable directory.
|
|
53
|
+
|
|
54
|
+
## Size and eviction
|
|
55
|
+
|
|
56
|
+
A project's active cache set is small (around 2 MB). Entries
|
|
57
|
+
are content-keyed, so events like a gem upgrade or an `.rbs`
|
|
58
|
+
edit write fresh entries and leave the old ones *orphaned* —
|
|
59
|
+
nothing references them, and no run would otherwise delete
|
|
60
|
+
them. To reap those, Rigor evicts least-recently-used entries
|
|
61
|
+
at the end of a run once the cache directory exceeds
|
|
62
|
+
`cache.max_bytes` (default **256 MB** — far above any active
|
|
63
|
+
set, so eviction only ever touches orphans):
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
cache:
|
|
67
|
+
max_bytes: 67108864 # tighten the cap to 64 MB…
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
cache:
|
|
72
|
+
max_bytes: null # …or disable eviction entirely
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Incremental analysis
|
|
76
|
+
|
|
77
|
+
The cache above makes an *unchanged* project fast — a second
|
|
78
|
+
run over the same files reuses the whole result. `rigor check
|
|
79
|
+
--incremental` goes further: when you have edited a few files,
|
|
80
|
+
it re-analyses **only those files plus the files that depend on
|
|
81
|
+
them**, and serves every other file's diagnostics from a
|
|
82
|
+
snapshot of the previous run. Editing a leaf controller
|
|
83
|
+
re-checks one file; editing a model re-checks the model and its
|
|
84
|
+
callers — not the whole project.
|
|
85
|
+
|
|
86
|
+
The diagnostics are identical to a full run. Rigor records, per
|
|
87
|
+
file, which other files its analysis read from, so it knows
|
|
88
|
+
exactly which files an edit can affect. A continuous-integration
|
|
89
|
+
gate, `rigor check --verify-incremental`, asserts this on every
|
|
90
|
+
build: it runs the incremental analyzer and a full analysis and
|
|
91
|
+
fails if they disagree on a single diagnostic.
|
|
92
|
+
|
|
93
|
+
The snapshot lives under the cache directory (`.rigor/cache`)
|
|
94
|
+
and is keyed by a fingerprint of your configuration, your locked
|
|
95
|
+
gems, your project's own `sig/` RBS, and the Rigor version.
|
|
96
|
+
Change any of those and the snapshot is dropped and the next run
|
|
97
|
+
is a full one, so an incremental run can never serve a stale
|
|
98
|
+
result. (The fingerprint keys on the analysis *roots* — e.g.
|
|
99
|
+
`["lib"]` — not the expanded file list, so adding or removing a
|
|
100
|
+
file *under* those roots does **not** drop the snapshot: the
|
|
101
|
+
incremental session re-analyzes the added files and the
|
|
102
|
+
dependents of removed ones.) As with the rest of the cache, a
|
|
103
|
+
missing or corrupt snapshot is simply a full run; it can never
|
|
104
|
+
wedge analysis.
|
|
105
|
+
|
|
106
|
+
`--incremental` is most useful for fast local re-checks and CI
|
|
107
|
+
on a changed branch. For a one-shot run on an unchanged project,
|
|
108
|
+
the ordinary cache already serves the whole result in one step.
|
|
109
|
+
|
|
110
|
+
## Concurrency
|
|
111
|
+
|
|
112
|
+
The cache is safe to share. Parallel worker processes
|
|
113
|
+
(`--workers=N`) and multiple editor LSP sessions against the
|
|
114
|
+
same project coordinate through atomic, locked writes; the LSP
|
|
115
|
+
opens the cache read-only, so it never races a `rigor check`
|
|
116
|
+
running alongside it.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Common problems and their fixes. For editor-specific issues,
|
|
4
|
+
see [Editor integration](09-editor-integration.md); for "why
|
|
5
|
+
did this diagnostic (not) fire", see
|
|
6
|
+
[handbook chapter 8](../handbook/08-understanding-errors.md).
|
|
7
|
+
|
|
8
|
+
## `rigor: command not found`
|
|
9
|
+
|
|
10
|
+
Rigor is installed but not on your `PATH`. With a version
|
|
11
|
+
manager this usually means the shell is not activated — see
|
|
12
|
+
[Installing Rigor](01-installation.md). As a stop-gap,
|
|
13
|
+
`mise exec gem:rigortype -- rigor …` runs it explicitly.
|
|
14
|
+
|
|
15
|
+
## `rigor check` analyses nothing
|
|
16
|
+
|
|
17
|
+
Rigor checks the `paths:` from the configuration file when no
|
|
18
|
+
paths are given on the command line. If `paths:` is wrong, or
|
|
19
|
+
no config file was found, the run is empty. Confirm a
|
|
20
|
+
`.rigor.yml` or `.rigor.dist.yml` exists at the project root,
|
|
21
|
+
or pass paths explicitly: `rigor check lib app`.
|
|
22
|
+
|
|
23
|
+
## Everything is `untyped` / `Dynamic[top]`
|
|
24
|
+
|
|
25
|
+
Rigor has no type information for the code in question. The
|
|
26
|
+
usual causes:
|
|
27
|
+
|
|
28
|
+
- **A gem ships no RBS.** Install signatures with
|
|
29
|
+
`rbs collection install`, or opt into
|
|
30
|
+
`dependencies.source_inference` (see
|
|
31
|
+
[Configuration](03-configuration.md)).
|
|
32
|
+
- **A framework needs a plugin.** Rails, RSpec, dry-rb and
|
|
33
|
+
others are only legible to Rigor through a
|
|
34
|
+
[plugin](07-plugins.md).
|
|
35
|
+
- **A project monkey-patch is invisible.** List the patching
|
|
36
|
+
files under `pre_eval:` so Rigor walks them first.
|
|
37
|
+
|
|
38
|
+
`rigor type-of FILE:LINE:COL` reports the exact type at a
|
|
39
|
+
point, which narrows down where the information is lost.
|
|
40
|
+
|
|
41
|
+
## Too many diagnostics to act on
|
|
42
|
+
|
|
43
|
+
A first run on a large, untyped project can report hundreds of
|
|
44
|
+
diagnostics. Do not start by suppressing them one by one:
|
|
45
|
+
|
|
46
|
+
1. `rigor triage` — see which rules and files dominate, with
|
|
47
|
+
hints about likely causes.
|
|
48
|
+
2. Fix the systemic causes triage points at — a missing
|
|
49
|
+
plugin, a missing RBS bundle.
|
|
50
|
+
3. `rigor baseline generate` — snapshot the rest so CI tracks
|
|
51
|
+
only new diagnostics. See [Baselines](06-baseline.md).
|
|
52
|
+
|
|
53
|
+
The [`rigor-project-init` skill](08-skills.md) automates this
|
|
54
|
+
sequence.
|
|
55
|
+
|
|
56
|
+
## A diagnostic is wrong (a false positive)
|
|
57
|
+
|
|
58
|
+
Rigor aims never to flag working code, so a genuine false
|
|
59
|
+
positive is a bug worth reporting. In the meantime, suppress
|
|
60
|
+
the single site with a `# rigor:disable <rule>` comment (see
|
|
61
|
+
[Diagnostics](04-diagnostics.md)) — prefer that over a
|
|
62
|
+
project-wide `disable:`, which also hides real instances.
|
|
63
|
+
|
|
64
|
+
Before reporting, rule out a missing RBS source. A burst of
|
|
65
|
+
`call.undefined-method` on calls you know exist usually means
|
|
66
|
+
Rigor never loaded their signatures. Check `rigor check`'s
|
|
67
|
+
STDERR for a `rigor: …` config-validation warning — a typo'd
|
|
68
|
+
or moved `signature_paths:` / `libraries:` entry (or an
|
|
69
|
+
explicit `bundler` / `rbs_collection` path that no longer
|
|
70
|
+
exists) loads zero signatures silently, and every call into
|
|
71
|
+
the types it was meant to cover then fires at
|
|
72
|
+
`evidence_tier: high`. Correct the configured value and the
|
|
73
|
+
false positives clear. (The same warnings cover an inert
|
|
74
|
+
`disable:` / `severity_overrides:` rule id — a typo there
|
|
75
|
+
leaves the rule firing as if you never suppressed it.) See
|
|
76
|
+
[Configuration § Config validation warnings](03-configuration.md#config-validation-warnings).
|
|
77
|
+
|
|
78
|
+
If the diagnostic is *correct* but you are not ready to fix
|
|
79
|
+
it, a [baseline](06-baseline.md) is the right tool.
|
|
80
|
+
|
|
81
|
+
## A result looks stale
|
|
82
|
+
|
|
83
|
+
It should not — cache entries are keyed by content and
|
|
84
|
+
invalidate themselves (see [Caching](12-caching.md)). If you
|
|
85
|
+
suspect the cache anyway, `rigor check --clear-cache` rules it
|
|
86
|
+
out. A result that survives a cleared cache is real analyzer
|
|
87
|
+
behaviour, not a caching artefact.
|
|
88
|
+
|
|
89
|
+
## The run is slow
|
|
90
|
+
|
|
91
|
+
- Let the cache warm up — the first run is the slow one.
|
|
92
|
+
- Narrow `paths:` and widen `exclude:` so Rigor is not walking
|
|
93
|
+
generated or vendored code.
|
|
94
|
+
- For a large project, `rigor check --workers=N` spreads
|
|
95
|
+
per-file analysis across parallel worker processes (or set
|
|
96
|
+
`RIGOR_RACTOR_WORKERS=N`).
|
|
97
|
+
|
|
98
|
+
## Advanced diagnostics
|
|
99
|
+
|
|
100
|
+
When a class infers worse than you expect, or a run uses more
|
|
101
|
+
memory than you expect, three environment variables make Rigor
|
|
102
|
+
report on *itself*. They print to stderr after `rigor check`
|
|
103
|
+
finishes and are no-ops when unset. They are process-global
|
|
104
|
+
counters, so run single-process (`--workers 0`) for meaningful
|
|
105
|
+
numbers.
|
|
106
|
+
|
|
107
|
+
| Variable | Reports |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| `RIGOR_BUDGET_TRACE=1` | How often inference hit a built-in cutoff (recursion guard, ancestor-walk limit, HKT fuel, …) and silently degraded to `Dynamic[top]`, plus the union-size distribution. The fastest way to see *where* inference gave up. |
|
|
110
|
+
| `RIGOR_HEAP_PROFILE=1` | A live-heap breakdown by class after a forced GC, ranked by memory — what the resident heap is actually made of (type carriers, RBS objects, Prism nodes, …). Walking the whole heap is slow; use it as a probe, not on every run. |
|
|
111
|
+
| `RIGOR_HEAP_TRACE=1` | The top String allocation sites by `file:line`. Very high overhead — run it on a small file subset only. |
|
|
112
|
+
|
|
113
|
+
These are intended for diagnosing Rigor itself or filing a
|
|
114
|
+
detailed bug report, not for day-to-day use.
|
|
115
|
+
|
|
116
|
+
## Reporting a bug
|
|
117
|
+
|
|
118
|
+
Open a GitHub issue with the Rigor version (`rigor version`),
|
|
119
|
+
the command you ran, a minimal reproduction, and — for a
|
|
120
|
+
suspected false positive — what you expected Rigor to infer.
|