rigortype 0.2.9 → 0.3.1
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 +2 -2
- data/data/builtins/ruby_core/array.yml +416 -392
- data/data/builtins/ruby_core/file.yml +42 -42
- data/data/builtins/ruby_core/hash.yml +302 -302
- data/data/builtins/ruby_core/io.yml +191 -191
- data/data/builtins/ruby_core/numeric.yml +321 -366
- data/data/builtins/ruby_core/proc.yml +124 -124
- data/data/builtins/ruby_core/range.yml +21 -21
- data/data/builtins/ruby_core/rational.yml +39 -39
- data/data/builtins/ruby_core/re.yml +65 -65
- data/data/builtins/ruby_core/set.yml +106 -106
- data/data/builtins/ruby_core/struct.yml +14 -14
- data/data/core_overlay/string_scanner.rbs +6 -5
- data/docs/handbook/01-getting-started.md +22 -34
- data/docs/handbook/03-narrowing.md +2 -1
- data/docs/handbook/04-tuples-and-shapes.md +7 -3
- data/docs/handbook/06-classes.md +19 -10
- data/docs/handbook/07-rbs-and-extended.md +76 -101
- data/docs/handbook/08-understanding-errors.md +114 -246
- data/docs/handbook/09-plugins.md +54 -144
- data/docs/handbook/11-sig-gen.md +11 -1
- data/docs/handbook/README.md +5 -3
- data/docs/handbook/appendix-liskov.md +4 -2
- data/docs/handbook/appendix-mypy.md +4 -3
- data/docs/handbook/appendix-phpstan.md +14 -7
- data/docs/handbook/appendix-steep.md +4 -2
- data/docs/handbook/appendix-type-theory.md +3 -1
- data/docs/install.md +14 -6
- data/docs/manual/01-installation.md +98 -4
- data/docs/manual/02-cli-reference.md +81 -12
- data/docs/manual/03-configuration.md +34 -2
- data/docs/manual/04-diagnostics.md +59 -4
- data/docs/manual/06-baseline.md +35 -1
- data/docs/manual/07-plugins.md +4 -4
- data/docs/manual/08-skills.md +6 -1
- data/docs/manual/09-editor-integration.md +7 -6
- data/docs/manual/11-ci.md +51 -0
- data/docs/manual/12-caching.md +65 -0
- data/docs/manual/plugins/rigor-actioncable.md +32 -0
- data/docs/manual/plugins/rigor-devise.md +4 -2
- data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +9 -1
- data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +5 -3
- data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +128 -0
- data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +60 -0
- data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -2
- data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +117 -0
- data/lib/rigor/analysis/check_rules/rule_ids.rb +125 -0
- data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
- data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +2 -1
- data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +283 -0
- data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +10 -1
- data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +112 -0
- data/lib/rigor/analysis/check_rules.rb +581 -98
- data/lib/rigor/analysis/dependency_recorder.rb +93 -9
- data/lib/rigor/analysis/dependency_source_inference/walker.rb +2 -1
- data/lib/rigor/analysis/incremental_session.rb +456 -51
- data/lib/rigor/analysis/path_expansion.rb +42 -0
- data/lib/rigor/analysis/plugin_fact_fingerprint.rb +188 -0
- data/lib/rigor/analysis/rule_catalog.rb +226 -1
- data/lib/rigor/analysis/run_cache_key.rb +78 -0
- data/lib/rigor/analysis/run_cache_probe.rb +72 -0
- data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +181 -28
- data/lib/rigor/analysis/runner/pool_coordinator.rb +77 -15
- data/lib/rigor/analysis/runner/project_pre_passes.rb +95 -49
- data/lib/rigor/analysis/runner/run_snapshots.rb +9 -2
- data/lib/rigor/analysis/runner.rb +344 -68
- data/lib/rigor/analysis/severity_stamp.rb +43 -0
- data/lib/rigor/analysis/worker_session.rb +30 -2
- data/lib/rigor/bleeding_edge.rb +37 -8
- data/lib/rigor/builtins/regex_refinement.rb +36 -1
- data/lib/rigor/cache/descriptor.rb +88 -28
- data/lib/rigor/cache/file_digest.rb +158 -0
- data/lib/rigor/cache/incremental_snapshot.rb +41 -5
- data/lib/rigor/cache/rbs_cache_producer.rb +11 -1
- data/lib/rigor/cache/rbs_descriptor.rb +56 -10
- data/lib/rigor/cache/rbs_environment_marshal_patch.rb +38 -0
- data/lib/rigor/cache/store.rb +132 -27
- data/lib/rigor/ci_detector.rb +90 -0
- data/lib/rigor/cli/annotate_command.rb +15 -9
- data/lib/rigor/cli/baseline_command.rb +4 -1
- data/lib/rigor/cli/check_command.rb +223 -32
- data/lib/rigor/cli/check_invocation.rb +84 -0
- data/lib/rigor/cli/coverage_command.rb +6 -1
- data/lib/rigor/cli/docs_command.rb +0 -30
- data/lib/rigor/cli/doctor_command.rb +169 -31
- data/lib/rigor/cli/lsp_command.rb +5 -0
- data/lib/rigor/cli/mcp_command.rb +5 -0
- data/lib/rigor/cli/plugins_command.rb +36 -6
- data/lib/rigor/cli/plugins_renderer.rb +44 -12
- data/lib/rigor/cli/probe_environment.rb +85 -0
- data/lib/rigor/cli/sig_gen_command.rb +36 -9
- data/lib/rigor/cli/skill_command.rb +22 -33
- data/lib/rigor/cli/skill_deep_probe.rb +172 -0
- data/lib/rigor/cli/skill_describe.rb +75 -9
- data/lib/rigor/cli/trace_command.rb +5 -6
- data/lib/rigor/cli/type_of_command.rb +9 -8
- data/lib/rigor/cli/type_scan_command.rb +8 -8
- data/lib/rigor/cli.rb +15 -4
- data/lib/rigor/config_audit.rb +48 -2
- data/lib/rigor/configuration/severity_profile.rb +31 -0
- data/lib/rigor/configuration.rb +156 -8
- data/lib/rigor/environment/default_libraries.rb +36 -0
- data/lib/rigor/environment/rbs_loader.rb +164 -5
- data/lib/rigor/environment.rb +29 -28
- data/lib/rigor/inference/budget_trace.rb +77 -2
- data/lib/rigor/inference/closure_escape_analyzer.rb +14 -1
- data/lib/rigor/inference/def_handle.rb +23 -0
- data/lib/rigor/inference/def_node_resolver.rb +90 -0
- data/lib/rigor/inference/def_return_typer.rb +2 -1
- data/lib/rigor/inference/expression_typer.rb +361 -113
- data/lib/rigor/inference/method_dispatcher/data_folding.rb +30 -5
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +200 -0
- data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +22 -16
- data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +33 -0
- data/lib/rigor/inference/method_dispatcher/overload_selector.rb +17 -1
- data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +42 -9
- data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +5 -0
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +28 -35
- data/lib/rigor/inference/method_dispatcher/struct_folding.rb +40 -8
- data/lib/rigor/inference/method_dispatcher.rb +57 -1
- data/lib/rigor/inference/mutation_widening.rb +42 -8
- data/lib/rigor/inference/narrowing.rb +127 -17
- data/lib/rigor/inference/parameter_inference_collector.rb +15 -0
- data/lib/rigor/inference/project_patched_scanner.rb +2 -1
- data/lib/rigor/inference/rbs_type_translator.rb +8 -1
- data/lib/rigor/inference/scope_indexer.rb +451 -36
- data/lib/rigor/inference/statement_evaluator.rb +64 -15
- data/lib/rigor/inference/struct_fold_safety.rb +48 -11
- data/lib/rigor/inference/synthetic_method_scanner.rb +15 -14
- data/lib/rigor/inference/void_origin.rb +25 -0
- data/lib/rigor/inference/void_tail_summary.rb +220 -0
- data/lib/rigor/language_server/buffer_resolution.rb +6 -3
- data/lib/rigor/language_server/buffer_table.rb +46 -6
- data/lib/rigor/language_server/completion_provider.rb +2 -1
- data/lib/rigor/language_server/diagnostic_publisher.rb +4 -0
- data/lib/rigor/language_server/document_symbol_provider.rb +2 -1
- data/lib/rigor/language_server/folding_range_provider.rb +2 -1
- data/lib/rigor/language_server/incremental_sync.rb +159 -0
- data/lib/rigor/language_server/selection_range_provider.rb +2 -1
- data/lib/rigor/language_server/server.rb +19 -9
- data/lib/rigor/language_server/signature_help_provider.rb +2 -1
- data/lib/rigor/language_server.rb +1 -0
- data/lib/rigor/plugin/base.rb +38 -24
- data/lib/rigor/plugin/inflector.rb +12 -3
- data/lib/rigor/plugin/io_boundary.rb +5 -1
- data/lib/rigor/plugin/isolation.rb +81 -11
- data/lib/rigor/plugin/load_error.rb +10 -1
- data/lib/rigor/plugin/loader.rb +96 -14
- data/lib/rigor/plugin/node_rule_walk.rb +5 -3
- data/lib/rigor/plugin/registry.rb +32 -23
- data/lib/rigor/plugin.rb +26 -0
- data/lib/rigor/protection/mutator.rb +3 -2
- data/lib/rigor/reflection.rb +64 -0
- data/lib/rigor/runtime/jit.rb +128 -0
- data/lib/rigor/scope/discovery_index.rb +12 -2
- data/lib/rigor/scope.rb +122 -28
- data/lib/rigor/sig_gen/classification.rb +5 -1
- data/lib/rigor/sig_gen/generator.rb +38 -6
- data/lib/rigor/sig_gen/observation_collector.rb +4 -3
- data/lib/rigor/sig_gen/rbs_validity.rb +44 -0
- data/lib/rigor/sig_gen/renderer.rb +10 -0
- data/lib/rigor/sig_gen/write_result.rb +9 -4
- data/lib/rigor/sig_gen/writer.rb +207 -49
- data/lib/rigor/source/node_children.rb +116 -0
- data/lib/rigor/source/node_locator.rb +3 -1
- data/lib/rigor/source/node_walker.rb +4 -2
- data/lib/rigor/source.rb +1 -0
- data/lib/rigor/type/difference.rb +28 -24
- data/lib/rigor/type/hash_shape.rb +34 -10
- data/lib/rigor/version.rb +1 -1
- data/lib/rigortype.rb +24 -0
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +4 -2
- data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb +51 -1
- data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +6 -4
- data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +5 -3
- data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +4 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +3 -1
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +4 -2
- data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +4 -2
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +3 -1
- data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +4 -2
- data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +38 -6
- data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +3 -1
- data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +3 -1
- data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +10 -0
- data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +11 -0
- data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +3 -1
- data/plugins/rigor-rails/lib/rigor-rails.rb +11 -12
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +3 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +3 -1
- data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +7 -5
- data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +83 -9
- data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +9 -5
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +3 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +3 -1
- data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +11 -0
- data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +4 -1
- data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +4 -2
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +3 -1
- data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +74 -14
- data/sig/prism_node_children.rbs +9 -0
- data/sig/rigor/cache.rbs +6 -0
- data/sig/rigor/inference/void_origin.rbs +18 -0
- data/sig/rigor/inference.rbs +7 -0
- data/sig/rigor/plugin/base.rbs +6 -6
- data/sig/rigor/reflection.rbs +1 -0
- data/sig/rigor/scope.rbs +12 -1
- data/skills/rigor-ci-setup/SKILL.md +10 -0
- data/skills/rigor-editor-setup/SKILL.md +11 -0
- data/skills/rigor-next-steps/SKILL.md +23 -2
- data/skills/rigor-plugin-author/SKILL.md +3 -3
- data/skills/rigor-plugin-author/references/02-walker-and-types.md +2 -2
- data/skills/rigor-plugin-review/SKILL.md +2 -2
- data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +5 -4
- data/skills/rigor-project-init/SKILL.md +29 -3
- data/skills/rigor-project-init/references/01-detect.md +1 -1
- data/skills/rigor-project-init/references/02-configure.md +39 -5
- data/skills/rigor-project-init/references/03-baseline-and-bugs.md +20 -0
- data/skills/rigor-project-init/references/05-jit-performance.md +125 -0
- metadata +48 -26
- data/lib/rigor/cli/ci_detector.rb +0 -89
data/docs/handbook/README.md
CHANGED
|
@@ -56,9 +56,11 @@ up the flag, key, or command that *acts* on it.
|
|
|
56
56
|
how to nudge it through `.rbs` files and `%a{rigor:v1:…}`
|
|
57
57
|
directives.
|
|
58
58
|
8. [**Understanding errors**](08-understanding-errors.md) —
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
reading a diagnostic: what each rule family claims, why one
|
|
60
|
+
fires when you did not expect it (and stays silent when you
|
|
61
|
+
did), and which layer to reach for when you want it quieter.
|
|
62
|
+
The catalogue itself is
|
|
63
|
+
[manual — Diagnostics](../manual/04-diagnostics.md).
|
|
62
64
|
9. [**Plugins**](09-plugins.md) — when to author one,
|
|
63
65
|
pointer to the [examples/](../../examples/README.md)
|
|
64
66
|
landing page.
|
|
@@ -571,8 +571,10 @@ model"](appendix-type-theory.md#what-rigor-does-not-model) records.
|
|
|
571
571
|
authoring the declared contracts `def.return-type-mismatch` checks
|
|
572
572
|
against.
|
|
573
573
|
- [Chapter 8 — Understanding errors](08-understanding-errors.md) for
|
|
574
|
-
the `def
|
|
575
|
-
|
|
574
|
+
what the `def.*` family claims, and
|
|
575
|
+
[manual — Diagnostics](../manual/04-diagnostics.md) for the
|
|
576
|
+
`def.return-type-mismatch` / `call.argument-type-mismatch`
|
|
577
|
+
entries and the severity profiles.
|
|
576
578
|
|
|
577
579
|
If you want to compare against another *tool* rather than the
|
|
578
580
|
*principle*, the sibling appendices cover
|
|
@@ -345,9 +345,10 @@ def shout: (String s) -> non-empty-string
|
|
|
345
345
|
|
|
346
346
|
You gain: `s.empty?` is a recognised refinement narrower (no
|
|
347
347
|
need for `assert s`). `match?(/\A\d+\z/)` does not yet narrow
|
|
348
|
-
to `numeric-string` (
|
|
349
|
-
[
|
|
350
|
-
behaviour will mirror `s.isdigit()` narrowing in
|
|
348
|
+
to `numeric-string` (queued as
|
|
349
|
+
[#164](https://github.com/rigortype/rigor/issues/164)), but the
|
|
350
|
+
eventual behaviour will mirror `s.isdigit()` narrowing in
|
|
351
|
+
Pyright.
|
|
351
352
|
|
|
352
353
|
## What's next
|
|
353
354
|
|
|
@@ -72,8 +72,10 @@ in another tab, almost every advanced refinement transfers.
|
|
|
72
72
|
## The `@phpstan-assert` family
|
|
73
73
|
|
|
74
74
|
PHPStan's assertion-narrowing PHPDoc tags map directly onto
|
|
75
|
-
Rigor's `RBS::Extended` directive grammar.
|
|
76
|
-
|
|
75
|
+
Rigor's `RBS::Extended` directive grammar. This is the mapping;
|
|
76
|
+
[Chapter 7](07-rbs-and-extended.md) works the Rigor side
|
|
77
|
+
through examples, and the directive reference itself is
|
|
78
|
+
[manual — RBS::Extended annotations](../manual/16-rbs-extended-annotations.md):
|
|
77
79
|
|
|
78
80
|
| PHPStan PHPDoc | Rigor RBS::Extended | Effect |
|
|
79
81
|
| --- | --- | --- |
|
|
@@ -149,7 +151,8 @@ Rigor has two baseline mechanisms: a **managed** baseline
|
|
|
149
151
|
the next `rigor check` via the `baseline:` config key — the
|
|
150
152
|
closest match to PHPStan's `--baseline`), and a **lightweight**
|
|
151
153
|
ad-hoc snapshot (`rigor diff` over a `--format=json` dump).
|
|
152
|
-
|
|
154
|
+
[Manual — Baselines](../manual/06-baseline.md) walks through
|
|
155
|
+
both.
|
|
153
156
|
|
|
154
157
|
The `includes:` semantics also match PHPStan's: declaration
|
|
155
158
|
order, later overrides earlier, the current file's keys win
|
|
@@ -322,11 +325,15 @@ You probably do not need to read the rest of this appendix
|
|
|
322
325
|
section sequentially. Three useful pointers:
|
|
323
326
|
|
|
324
327
|
- [Chapter 7 — RBS and `RBS::Extended`](07-rbs-and-extended.md)
|
|
325
|
-
|
|
326
|
-
table
|
|
328
|
+
works the directive grammar through examples; the reference
|
|
329
|
+
table is
|
|
330
|
+
[manual — RBS::Extended annotations](../manual/16-rbs-extended-annotations.md).
|
|
327
331
|
- [Chapter 8 — Understanding errors](08-understanding-errors.md)
|
|
328
|
-
|
|
329
|
-
|
|
332
|
+
explains how to read a diagnostic and which knob to reach
|
|
333
|
+
for; the catalogue, severity profiles and baselines — every
|
|
334
|
+
PHPStan onboarding analogue — are
|
|
335
|
+
[manual — Diagnostics](../manual/04-diagnostics.md) and
|
|
336
|
+
[manual — Baselines](../manual/06-baseline.md).
|
|
330
337
|
- [Chapter 9 — Plugins](09-plugins.md) for the
|
|
331
338
|
Type-Specifying / Dynamic-Return analogues.
|
|
332
339
|
|
|
@@ -321,8 +321,10 @@ section sequentially. Three useful pointers:
|
|
|
321
321
|
if you want to see how the directive grammar layers on top
|
|
322
322
|
of the RBS you already write.
|
|
323
323
|
- [Chapter 8 — Understanding errors](08-understanding-errors.md)
|
|
324
|
-
for
|
|
325
|
-
|
|
324
|
+
for how to read a diagnostic, and
|
|
325
|
+
[manual — Diagnostics](../manual/04-diagnostics.md) for the
|
|
326
|
+
rule catalogue and severity profiles — the analogue to
|
|
327
|
+
Steep's diagnostic config.
|
|
326
328
|
- [`docs/notes/20260503-steep-cross-check-triage.md`](../notes/20260503-steep-cross-check-triage.md)
|
|
327
329
|
for a worked side-by-side run of Steep and Rigor on the
|
|
328
330
|
same project (the project itself).
|
|
@@ -1651,7 +1651,9 @@ practical companion:
|
|
|
1651
1651
|
for the directive grammar that lets you teach Rigor about a
|
|
1652
1652
|
custom predicate.
|
|
1653
1653
|
- [Chapter 8 — Understanding errors](08-understanding-errors.md)
|
|
1654
|
-
for
|
|
1654
|
+
for how a diagnostic reads, and
|
|
1655
|
+
[manual — Diagnostics](../manual/04-diagnostics.md) for the
|
|
1656
|
+
rule catalogue (the user-visible end of the trinary
|
|
1655
1657
|
certainty).
|
|
1656
1658
|
|
|
1657
1659
|
If you want to compare against another *tool* rather than the
|
data/docs/install.md
CHANGED
|
@@ -37,19 +37,27 @@ Then proceed to the **first** matching case below.
|
|
|
37
37
|
and pins language runtimes (Ruby, Node, Python, …) and tool gems
|
|
38
38
|
(like `rigortype`) per project, recording versions in a `mise.toml`
|
|
39
39
|
that can be committed alongside the code. Other contributors — and CI
|
|
40
|
-
— run `mise install` to restore
|
|
41
|
-
|
|
40
|
+
— run `mise install` to restore those versions with no `Gemfile`
|
|
41
|
+
involvement.
|
|
42
42
|
|
|
43
43
|
Run in the project root:
|
|
44
44
|
|
|
45
45
|
```sh
|
|
46
46
|
mise use ruby@4.0
|
|
47
|
-
mise use gem:rigortype
|
|
47
|
+
mise use --pin gem:rigortype
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
`mise use` installs the tools and writes their versions to `mise.toml`
|
|
51
51
|
in one step. Commit `mise.toml` so the version is shared.
|
|
52
52
|
|
|
53
|
+
`--pin` records the exact Rigor version (`"gem:rigortype" = "0.2.9"`).
|
|
54
|
+
Without it mise writes `"gem:rigortype" = "latest"`, which every
|
|
55
|
+
machine re-resolves to whatever is newest when it first installs — so
|
|
56
|
+
a committed `latest` does not give the team one shared version. The
|
|
57
|
+
trade-off: a pin will not move on its own, and `mise outdated` cannot
|
|
58
|
+
report a pinned tool as behind. Upgrade with `mise upgrade --bump
|
|
59
|
+
gem:rigortype`.
|
|
60
|
+
|
|
53
61
|
Then verify:
|
|
54
62
|
|
|
55
63
|
```sh
|
|
@@ -184,6 +192,6 @@ project is set up, re-run `rigor skill describe` for the step after
|
|
|
184
192
|
that.
|
|
185
193
|
|
|
186
194
|
If `rigor skill describe` is not recognised, your Rigor version predates
|
|
187
|
-
it. Run `rigor --version` and upgrade with `mise
|
|
188
|
-
`gem update rigortype` for Case C
|
|
189
|
-
`rigor skill rigor-project-init` directly.
|
|
195
|
+
it. Run `rigor --version` and upgrade with `mise upgrade --bump
|
|
196
|
+
gem:rigortype` (or `gem update rigortype` for Case B/C); on an older
|
|
197
|
+
version, run `rigor skill rigor-project-init` directly.
|
|
@@ -244,9 +244,23 @@ A few things worth knowing if you have not used mise before:
|
|
|
244
244
|
*current directory* recording the chosen versions, and installs
|
|
245
245
|
the tools as part of the same command — there is no separate
|
|
246
246
|
install step. (mise also reads the asdf-style `.tool-versions`.)
|
|
247
|
-
- **Commit the config to share versions
|
|
248
|
-
`mise.toml` into Git so every
|
|
249
|
-
|
|
247
|
+
- **Commit the config to share versions — and pass `--pin` if you
|
|
248
|
+
mean it.** Check the generated `mise.toml` into Git so every
|
|
249
|
+
contributor, and every CI run, resolves the same versions. Note
|
|
250
|
+
what the two commands above actually record, because they differ:
|
|
251
|
+
`mise use ruby@4.0` preserves the precision you asked for and
|
|
252
|
+
writes `ruby = "4.0"` (any 4.0.x), but `mise use gem:rigortype` has
|
|
253
|
+
no requested version to preserve and writes `"gem:rigortype" =
|
|
254
|
+
"latest"` — which resolves to whatever is newest *on each machine,
|
|
255
|
+
whenever that machine first installs it*. A committed `latest` is
|
|
256
|
+
not a shared version. To share one, pin it:
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
mise use --pin gem:rigortype # records e.g. "gem:rigortype" = "0.2.9"
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Then read [Keeping Rigor up to date](#keeping-rigor-up-to-date):
|
|
263
|
+
a pin is a version that will not move until you move it.
|
|
250
264
|
- **For a machine-wide install, add `-g`.** `mise use -g
|
|
251
265
|
gem:rigortype` writes mise's global config
|
|
252
266
|
(`~/.config/mise/config.toml`) instead of a project `mise.toml`,
|
|
@@ -284,6 +298,48 @@ explicitly with `mise exec gem:rigortype -- rigor`. See
|
|
|
284
298
|
[Editor integration](09-editor-integration.md) for the editor
|
|
285
299
|
side.
|
|
286
300
|
|
|
301
|
+
### Keeping Rigor up to date
|
|
302
|
+
|
|
303
|
+
Rigor ships often. How you upgrade depends on what your config
|
|
304
|
+
records — and in one case, on knowing that mise will not tell you an
|
|
305
|
+
upgrade exists.
|
|
306
|
+
|
|
307
|
+
- **`"gem:rigortype" = "latest"`** — what a plain `mise use
|
|
308
|
+
gem:rigortype` writes. `mise upgrade gem:rigortype` moves you to the
|
|
309
|
+
newest release.
|
|
310
|
+
- **An exact pin** — `"gem:rigortype" = "0.2.9"`, from `--pin` or from
|
|
311
|
+
`mise use gem:rigortype@0.2.9`. Here `mise upgrade` **will not move
|
|
312
|
+
it, and `mise outdated` will not report it.** Both compare the
|
|
313
|
+
installed version against the range the config asks for, and an
|
|
314
|
+
exact pin is a range containing only itself, so a pinned Rigor
|
|
315
|
+
reports itself up to date forever, however far behind it has fallen.
|
|
316
|
+
Use `--bump`, which installs the newest release *and* rewrites the
|
|
317
|
+
pin:
|
|
318
|
+
|
|
319
|
+
```sh
|
|
320
|
+
mise upgrade --bump gem:rigortype
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Neither is a bug to work around — a pin doing nothing is a pin working.
|
|
324
|
+
But it does mean a pinned setup has no passive signal that a new Rigor
|
|
325
|
+
exists: `--bump` is both how you look and how you move.
|
|
326
|
+
|
|
327
|
+
**After a Ruby change.** mise's `gem:` backend installs each tool
|
|
328
|
+
against the Ruby that was active at install time, and its
|
|
329
|
+
[gem backend docs](https://mise.jdx.dev/dev-tools/backends/gem.html)
|
|
330
|
+
note that "if the ruby version used by a gem package changes, (by mise
|
|
331
|
+
or system ruby), you may need to reinstall the gem". Rigor's pinned
|
|
332
|
+
`ruby@4.0` makes this rare — patch upgrades within 4.0.x are followed
|
|
333
|
+
automatically — but if you remove or replace that Ruby, reinstall:
|
|
334
|
+
|
|
335
|
+
```sh
|
|
336
|
+
mise install -f gem:rigortype # or, for every gem-backend tool:
|
|
337
|
+
mise install -f "gem:*"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
On a plain `gem install` (below), the equivalent is `gem update
|
|
341
|
+
rigortype`.
|
|
342
|
+
|
|
287
343
|
## asdf
|
|
288
344
|
|
|
289
345
|
`asdf` follows the same model. Install a Ruby 4.0.x with the
|
|
@@ -300,7 +356,8 @@ gem install rigortype
|
|
|
300
356
|
`asdf` has no general-purpose gem backend, so the gem itself is
|
|
301
357
|
installed with `gem install` rather than an `asdf` command. `mise`
|
|
302
358
|
(above) is the more integrated option because its `gem:` backend
|
|
303
|
-
|
|
359
|
+
records the gem in the same config that records Ruby, and — as the
|
|
360
|
+
next section explains — keeps the two from interfering.
|
|
304
361
|
|
|
305
362
|
## Simple alternative — gem install
|
|
306
363
|
|
|
@@ -316,6 +373,43 @@ quickest path, but it records nothing per project: a version
|
|
|
316
373
|
manager keeps the Rigor version pinned next to the project, so
|
|
317
374
|
local runs and CI cannot drift apart.
|
|
318
375
|
|
|
376
|
+
It also leaves Rigor sharing a Ruby with your work, which is the
|
|
377
|
+
deeper reason the version managers are listed first. The executable
|
|
378
|
+
RubyGems installs begins with `#!/usr/bin/env ruby`, so it runs under
|
|
379
|
+
whatever `ruby` is first on `PATH` *at the moment you invoke it* — and
|
|
380
|
+
because Rigor requires Ruby 4.0 while your projects pin their own,
|
|
381
|
+
running `rigor` inside a project on Ruby 3.x fails before it starts.
|
|
382
|
+
mise's `gem:` backend does not have this failure mode: it installs each
|
|
383
|
+
tool into its own private gem directory and points the executable at
|
|
384
|
+
the Ruby the tool was installed with, so a project's Ruby pin cannot
|
|
385
|
+
reach it. A `gem install` under a Ruby 4.0 you never switch away from
|
|
386
|
+
is perfectly fine; one that shares a Ruby with projects you switch
|
|
387
|
+
between is a footgun.
|
|
388
|
+
|
|
389
|
+
## If you want Bundler to manage the version
|
|
390
|
+
|
|
391
|
+
The rule at the top of this chapter is about your *application's*
|
|
392
|
+
`Gemfile` — the one Bundler resolves against your app's gems, and whose
|
|
393
|
+
entries `Bundler.require` loads at boot. It is not a rule against
|
|
394
|
+
Bundler. A `Gemfile` holding nothing but Rigor, resolved separately and
|
|
395
|
+
selected with `BUNDLE_GEMFILE`, keeps every property the prohibition
|
|
396
|
+
exists to protect: your application's dependency graph never meets
|
|
397
|
+
Rigor's, and your application's Ruby is never constrained by Rigor's.
|
|
398
|
+
|
|
399
|
+
That arrangement — a `Gemfile` under `.github/rigor/`, plus the
|
|
400
|
+
Dependabot config that keeps it current — is written up under
|
|
401
|
+
[Pinning Rigor's version](11-ci.md#pinning-rigors-version) in the CI
|
|
402
|
+
chapter. Nothing about it is CI-specific:
|
|
403
|
+
|
|
404
|
+
```sh
|
|
405
|
+
BUNDLE_GEMFILE=.github/rigor/Gemfile bundle exec rigor check
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
It is more moving parts than `mise use --pin gem:rigortype`, which
|
|
409
|
+
records the same version in one line and needs no `bundle exec`. Reach
|
|
410
|
+
for it when your team already runs everything through Bundler and wants
|
|
411
|
+
Rigor on the same footing — not as a first choice.
|
|
412
|
+
|
|
319
413
|
## Nix
|
|
320
414
|
|
|
321
415
|
If you use Nix, Rigor's flake exposes the executable as a package,
|
|
@@ -41,12 +41,12 @@ the `paths:` list from the configuration file.
|
|
|
41
41
|
| `--cache-stats` | Print the on-disk cache inventory when finished. |
|
|
42
42
|
| `--[no-]stats` | Print a run summary (files, classes, memory, wall time) to stderr. Default on. |
|
|
43
43
|
| `--coverage` | Add a type-precision coverage block to the output (`coverage` object under `--format json`; a one-line summary in text mode). Off by default — it is a second precision pass over the analyzed files, the same scan [`rigor coverage`](#rigor-coverage) runs, so it is opt-in. |
|
|
44
|
-
| `--workers=N` | Dispatch analysis across `N` parallel worker processes (fork-based pool today; ADR-15). Default `0` (sequential). |
|
|
44
|
+
| `--workers=N` | Dispatch analysis across `N` parallel worker processes (fork-based pool today; ADR-15). Default `0` (sequential). Applies to `--incremental` re-checks as well as full runs. |
|
|
45
45
|
| `--baseline=PATH` | Load a baseline file, overriding config. |
|
|
46
46
|
| `--no-baseline` | Ignore any configured baseline. |
|
|
47
47
|
| `--baseline-strict` | Fail the run on any baseline drift — a CI gate. |
|
|
48
48
|
| `--treat-all-as-inline-rbs` | Force-load `rigor-rbs-inline` with `require_magic_comment: false`, so every analysed file is treated as inline-RBS without the `# rbs_inline: enabled` comment (ADR-32). |
|
|
49
|
-
| `--bleeding-edge[=ids]` | Adopt the bleeding-edge overlay for this run, overriding the configured [`bleeding_edge:`](03-configuration.md) selection (ADR-50 § WD2). Bare adopts every queued feature; `--bleeding-edge=a,b` adopts only the named feature ids.
|
|
49
|
+
| `--bleeding-edge[=ids]` | Adopt the bleeding-edge overlay for this run, overriding the configured [`bleeding_edge:`](03-configuration.md) selection (ADR-50 § WD2). Bare adopts every queued feature; `--bleeding-edge=a,b` adopts only the named feature ids. Inspect it with [`rigor show-bleedingedge`](#rigor-show-bleedingedge). |
|
|
50
50
|
| `--no-bleeding-edge` | Ignore any configured `bleeding_edge:` selection for this run (adopt none). |
|
|
51
51
|
| `--tmp-file=PATH --instead-of=PATH` | Editor mode: analyse `PATH` using the buffer in `--tmp-file`. Both required together. |
|
|
52
52
|
|
|
@@ -183,6 +183,17 @@ rigor sig-gen [paths]
|
|
|
183
183
|
| `--new-files` / `--new-methods` / `--tighter-returns` | Emit only that classification. |
|
|
184
184
|
| `--format=text\|json` | Output format. |
|
|
185
185
|
|
|
186
|
+
Every signature is parsed before it is emitted. A method whose
|
|
187
|
+
generated RBS does not parse is **skipped** (`sig.skipped.unrenderable-rbs`)
|
|
188
|
+
and reported on stderr rather than written — an unparseable
|
|
189
|
+
`.rbs` is quarantined *whole* by `rigor check`, so one bad line
|
|
190
|
+
would take every other type in the file down with it. Under
|
|
191
|
+
`--write`, a file whose assembled content does not parse is
|
|
192
|
+
**refused** (the existing file is left untouched) and the command
|
|
193
|
+
exits `1`: you asked for a write and did not get one. Such a skip
|
|
194
|
+
is a bug in Rigor's RBS rendering, not in your code — please
|
|
195
|
+
report it.
|
|
196
|
+
|
|
186
197
|
## `rigor lsp`
|
|
187
198
|
|
|
188
199
|
Run the Language Server over stdio. See
|
|
@@ -400,6 +411,11 @@ Report the activation status of every plugin configured in
|
|
|
400
411
|
`.rigor.yml` — loaded, load-error (with reason), and each
|
|
401
412
|
plugin's declared extension surfaces. See [Plugins](07-plugins.md).
|
|
402
413
|
|
|
414
|
+
Each loaded plugin's row also reports the resolved file it
|
|
415
|
+
loaded from (a `path:` line in text, a `"path"` key in JSON), so
|
|
416
|
+
if a stale installed gem is shadowing a newer checkout's bundled
|
|
417
|
+
plugin copy the mismatch is visible at a glance.
|
|
418
|
+
|
|
403
419
|
```sh
|
|
404
420
|
rigor plugins [--format=text|json] [--strict] [--capabilities] [--config=PATH]
|
|
405
421
|
```
|
|
@@ -463,6 +479,7 @@ so a skill can never be shadowed by a verb.
|
|
|
463
479
|
|
|
464
480
|
```sh
|
|
465
481
|
rigor skill [<name>] [--full <name>] [--path <name>] [--list] [--describe]
|
|
482
|
+
rigor skill describe [--deep]
|
|
466
483
|
```
|
|
467
484
|
|
|
468
485
|
| Form | Purpose |
|
|
@@ -472,10 +489,38 @@ rigor skill [<name>] [--full <name>] [--path <name>] [--list] [--describe]
|
|
|
472
489
|
| `--full <name>` | Print the `SKILL.md` body **followed by every `references/*.md` inline** — the complete, version-current procedure in one call. This is what a skill's "First: load the version-current copy" directive points at, so a copy vendored into a project (e.g. via `npx skills add`) re-fetches its current steps from the installed gem instead of following a frozen copy. |
|
|
473
490
|
| `--path <name>` | Print the single-line absolute `SKILL.md` path, suitable as input to a file-reading tool. |
|
|
474
491
|
| `--describe` | Probe the project's state (config / baseline / `sig/` / CI — presence only, never runs `rigor check`) and recommend the next skill to run. Also spelled `describe`; surfaced top-level as [`rigor describe`](#rigor-describe) below. |
|
|
492
|
+
| `describe --deep` | The same report, except it **runs `rigor check` first** and routes the headline recommendation on the result. Opt-in, because it costs a full analysis and writes `.rigor/cache` — the un-flagged form stays presence-only and side-effect-free. |
|
|
493
|
+
|
|
494
|
+
### `describe --deep`
|
|
495
|
+
|
|
496
|
+
By default the recommendation comes from a presence-only probe, so it can
|
|
497
|
+
tell that a project *has* a config but not whether the analysis is
|
|
498
|
+
healthy. `--deep` runs the check for you and lets the result pick the
|
|
499
|
+
headline, using the same routing the `## For the agent` section already
|
|
500
|
+
teaches:
|
|
501
|
+
|
|
502
|
+
| Deep check result | Headline becomes |
|
|
503
|
+
| --- | --- |
|
|
504
|
+
| RBS environment built to 0 classes, or a `configuration-error` diagnostic | `rigor-doctor` — the analysis is hollow until the setup is fixed. |
|
|
505
|
+
| Call sites resolving to the project's own definitions (reopened core / gem classes), as at least a third of the errors | `rigor-monkeypatch-resolve` — list them in `pre_eval:` and they clear wholesale. |
|
|
506
|
+
| Any remaining error diagnostics | `rigor-baseline-reduce`. Proven monkey-patch sites below that share are still reported here, so the finding survives even when the headline stays on the larger problem. |
|
|
507
|
+
| Clean, or the project has no config yet | Unchanged — the presence-only recommendation stands. |
|
|
508
|
+
|
|
509
|
+
If the check **cannot run at all** (no config, an unloadable plugin, a
|
|
510
|
+
malformed config) `--deep` does not fail and does not pretend the project
|
|
511
|
+
is clean: it reports what went wrong, falls back to the presence-only
|
|
512
|
+
recommendation, and points you at `rigor doctor`. It deliberately does
|
|
513
|
+
*not* route on weaker signals — "framework calls typing as `Dynamic`" is
|
|
514
|
+
still a judgement call left to you and your agent.
|
|
515
|
+
|
|
516
|
+
```sh
|
|
517
|
+
rigor skill describe --deep # also: rigor describe --deep
|
|
518
|
+
```
|
|
475
519
|
|
|
476
520
|
The verb spellings `rigor skill list` / `print <name>` / `path <name>`
|
|
477
|
-
|
|
478
|
-
|
|
521
|
+
were **removed in v0.3.0** — the positional slot is a skill name, so
|
|
522
|
+
they now read as an unknown skill. Use the forms above.
|
|
523
|
+
`describe` / `--describe` stay first-class.
|
|
479
524
|
|
|
480
525
|
## `rigor describe`
|
|
481
526
|
|
|
@@ -494,6 +539,10 @@ It reports a presence-only project-state probe (does a `.rigor.yml`,
|
|
|
494
539
|
recommended next skill. It is read-only and side-effect-free — it never
|
|
495
540
|
runs `rigor check`. Identical output to `rigor skill describe`.
|
|
496
541
|
|
|
542
|
+
`rigor describe --deep` forwards to
|
|
543
|
+
[`rigor skill describe --deep`](#rigor-skill), which opts into running the
|
|
544
|
+
check first — slow, and it writes the cache.
|
|
545
|
+
|
|
497
546
|
## `rigor docs`
|
|
498
547
|
|
|
499
548
|
Print the documentation bundled inside the `rigortype` gem
|
|
@@ -518,8 +567,9 @@ rigor docs [<name>] [--path <name>] [--list [<category>]]
|
|
|
518
567
|
| `--path <name>` | Print the single-line absolute path of a doc, suitable as input to a file-reading tool. |
|
|
519
568
|
| `--list [<category>]` | Table of every bundled doc (name + absolute path); pass `manual` or `handbook` to filter. |
|
|
520
569
|
|
|
521
|
-
The verb spellings `rigor docs list` / `path <name>`
|
|
522
|
-
|
|
570
|
+
The verb spellings `rigor docs list` / `path <name>` were **removed in
|
|
571
|
+
v0.3.0** — the positional slot is a doc name, so they now read as an
|
|
572
|
+
unknown doc. Use `--list` / `--path`.
|
|
523
573
|
|
|
524
574
|
The canonical web copy of the index is
|
|
525
575
|
<https://rigor.typedduck.fail/llms.txt>; `rigor docs` serves the same
|
|
@@ -543,12 +593,16 @@ rigor show-bleedingedge [--config PATH] [--format text|json]
|
|
|
543
593
|
| `--config PATH` | Use this `.rigor.yml` instead of auto-discovery. |
|
|
544
594
|
| `--format text\|json` | Output format. Default `text`. |
|
|
545
595
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
596
|
+
Each queued feature appears with its stable id, the severity it imposes,
|
|
597
|
+
and whether your configuration adopts it. See
|
|
598
|
+
[`docs/compatibility.md`](../compatibility.md) for how bleeding-edge fits
|
|
599
|
+
the stability model.
|
|
600
|
+
|
|
601
|
+
Queued today:
|
|
602
|
+
|
|
603
|
+
| Feature id | What it changes |
|
|
604
|
+
| --- | --- |
|
|
605
|
+
| `reject-unparseable-signatures` | An unparseable `.rbs` under `signature_paths:` **fails the run** (`rbs.coverage.quarantined-signature` → `error`) instead of being skipped with a warning. |
|
|
552
606
|
|
|
553
607
|
## `rigor doctor`
|
|
554
608
|
|
|
@@ -575,6 +629,18 @@ Runs a scoped analysis and audits:
|
|
|
575
629
|
from the saved baseline.
|
|
576
630
|
- **Rails plugin gap** — whether `Gemfile.lock` contains Rails gems
|
|
577
631
|
but no Rails plugin is enabled.
|
|
632
|
+
- **Gemfile install** — whether Rigor itself resolves as one of the
|
|
633
|
+
project's dependencies, which
|
|
634
|
+
[Installing Rigor](01-installation.md) tells you not to do. Only a
|
|
635
|
+
`rigortype` resolved from a **GEM** remote counts: a `PATH` or `GIT`
|
|
636
|
+
source means you are developing or vendoring Rigor deliberately,
|
|
637
|
+
and Rigor's own repository looks exactly like that.
|
|
638
|
+
- **Plugin installation skew** — whether a plugin Rigor bundles
|
|
639
|
+
loaded from a different `rigortype` installation than the engine,
|
|
640
|
+
naming both paths. The engine and its bundled plugins are
|
|
641
|
+
versioned together, so a copy from another installation can run
|
|
642
|
+
the engine with a mismatched plugin. A warning, not a failure;
|
|
643
|
+
third-party plugins from your own bundle are never flagged.
|
|
578
644
|
|
|
579
645
|
Text output prints `[PASS]`, `[FAIL]`, or `[WARN]` per check plus a
|
|
580
646
|
routed hint (e.g. "Run `rigor baseline regenerate`"). JSON output
|
|
@@ -618,6 +684,9 @@ operational knobs read the environment instead.
|
|
|
618
684
|
| `RIGOR_RACTOR_WORKERS=N` | Worker count for parallel analysis. Sits between the CLI flag and the config key in precedence: `--workers=N` > `RIGOR_RACTOR_WORKERS` > `parallel.workers:` > `0` (sequential). |
|
|
619
685
|
| `RIGOR_POOL_BACKEND=ractor` | Opt back into the (off-by-default) Ractor worker pool instead of the active fork-based pool ([ADR-15](../adr/15-ractor-concurrency.md)). Only relevant with a non-zero worker count; the fork pool is the supported backend. |
|
|
620
686
|
| `RIGOR_PLUGIN_ISOLATION=none\|process\|ruby_box` | How a plugin's direct calls into its target library are isolated. Default `process`. See [Using plugins § Isolation strategy](07-plugins.md). `RIGOR_BOX` is a legacy alias for `ruby_box`. |
|
|
687
|
+
| `RIGOR_STRICT_VALIDATION=1` | Force full-content cache validation for one run (the same as `cache.validation: digest`, and winning over it) — re-hash every file's content instead of trusting its stat metadata. Use it if a filesystem's timestamps or inode numbers cannot be trusted. See [Caching § How a file is checked for changes](12-caching.md#how-a-file-is-checked-for-changes). |
|
|
688
|
+
| `RIGOR_DISABLE_YJIT=1` | Opt out of Rigor's deferred YJIT enablement. Rigor turns YJIT on partway through a long `check` / `coverage` run so short runs never pay the JIT warm-up; this variable leaves it off entirely. Diagnostics and allocations are identical either way — the effect is wall-time only. |
|
|
689
|
+
| `RIGOR_YJIT_DEADLINE=<seconds>` | Advanced: tune how long a run must last before deferred YJIT enables (default `5.0`). Lower it if your runs are long and you want the JIT sooner; raise it to protect short runs. Ignored when `RIGOR_DISABLE_YJIT=1` is set or YJIT is unavailable. |
|
|
621
690
|
|
|
622
691
|
Three further variables (`RIGOR_BUDGET_TRACE`,
|
|
623
692
|
`RIGOR_HEAP_PROFILE`, `RIGOR_HEAP_TRACE`) enable developer-facing
|
|
@@ -22,6 +22,24 @@ discovery entirely.
|
|
|
22
22
|
All relative paths in a config file resolve against that
|
|
23
23
|
file's own directory.
|
|
24
24
|
|
|
25
|
+
## Editor validation
|
|
26
|
+
|
|
27
|
+
Rigor ships a JSON Schema for this file. Editors that
|
|
28
|
+
understand the [`yaml-language-server`](https://github.com/redhat-developer/yaml-language-server)
|
|
29
|
+
magic comment — VS Code's YAML extension, the IntelliJ
|
|
30
|
+
family, Helix, Neovim with `yaml-ls` — give you
|
|
31
|
+
autocomplete, hover docs, and structural validation as you
|
|
32
|
+
type:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
# yaml-language-server: $schema=https://github.com/rigortype/rigor/raw/master/schemas/rigor-config.schema.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`rigor init` writes that line for you. The schema is not a
|
|
39
|
+
copy of this page — it is a source of truth in its own
|
|
40
|
+
right, kept in step with the loader by a spec, so a key it
|
|
41
|
+
rejects is a key Rigor does not accept.
|
|
42
|
+
|
|
25
43
|
## A minimal config
|
|
26
44
|
|
|
27
45
|
```yaml
|
|
@@ -44,6 +62,7 @@ cache:
|
|
|
44
62
|
| `exclude` | Array | `[]` | Glob patterns to skip. `vendor/bundle`, `.bundle`, and `node_modules` are always excluded. |
|
|
45
63
|
| `includes` | Array | `[]` | Other config files to layer underneath this one. |
|
|
46
64
|
| `fold_platform_specific_paths` | Boolean | `false` | Resolve Ruby-version-conditional load paths when discovering sources. |
|
|
65
|
+
| `parameter_inference` | Boolean | `false` | Opt-in call-site parameter type inference on the `check` walk ([ADR-67](../adr/67-parameter-type-inference.md) WD6). When `true`, an undeclared `def` / `initialize` / setter parameter is typed to the union of its resolved call-site argument types, sharpening downstream ivar reads, folds, and protection coverage. Precision-additive only — the negative rules never fire against an inferred parameter. Cannot be combined with `--incremental`. |
|
|
47
66
|
|
|
48
67
|
### Type sources
|
|
49
68
|
|
|
@@ -65,6 +84,7 @@ types it was meant to describe into a high-confidence
|
|
|
65
84
|
of real type errors. The audit covers:
|
|
66
85
|
|
|
67
86
|
```
|
|
87
|
+
rigor: `excludee` is not a recognized configuration key; it has no effect. Did you mean `exclude`?
|
|
68
88
|
rigor: signature_paths: "/path/to/sig" does not exist (no signatures loaded from it)
|
|
69
89
|
rigor: signature_paths: "/path/to/sig" matched 0 signature files
|
|
70
90
|
rigor: libraries: "csb" is not an available RBS library (no signatures loaded from it)
|
|
@@ -73,6 +93,11 @@ rigor: severity_overrides: "flow.bogus" is not a recognized rule id; the overrid
|
|
|
73
93
|
rigor: bundler.lockfile: "./missing/Gemfile.lock" does not exist
|
|
74
94
|
```
|
|
75
95
|
|
|
96
|
+
The unrecognised-key check covers **top-level** keys, and skips
|
|
97
|
+
the namespaces reserved for other implementations (see below).
|
|
98
|
+
A typo *inside* a group — `cache: { pth: … }` — is caught by
|
|
99
|
+
the JSON schema as you type rather than at check time.
|
|
100
|
+
|
|
76
101
|
These are warnings, not errors — partial or optional bundles and
|
|
77
102
|
forward-looking config are valid setups. The audit only fires on explicit,
|
|
78
103
|
working-setup-safe signals: an unset default (auto-detected `<root>/sig`,
|
|
@@ -91,7 +116,7 @@ statically and may resolve at run time. The same findings appear in the
|
|
|
91
116
|
| `severity_profile` | String | `"balanced"` | `lenient`, `balanced`, or `strict` — see [Diagnostics](04-diagnostics.md). |
|
|
92
117
|
| `severity_overrides` | Hash | `{}` | Per-rule / per-family severity, e.g. `{ call: warning, flow.always-truthy-condition: off }`. |
|
|
93
118
|
| `baseline` | String / `false` | `nil` | Path to a `.rigor-baseline.yml`, or `false` to disable an inherited one. See [Baselines](06-baseline.md). |
|
|
94
|
-
| `bleeding_edge` | Boolean / Array / Hash | `false` | Adopt the next major's queued diagnostic disciplines early ([ADR-50](../adr/50-release-engineering-and-stability-strategy.md) § WD2). `false` adopts none; `true` adopts the whole overlay; a list of feature ids adopts only those; `{ all: true, except: [ids] }` adopts all but the named. Orthogonal to `severity_profile`. Override it for a single run with [`rigor check --bleeding-edge[=ids]`](02-cli-reference.md#rigor-check) / `--no-bleeding-edge`. Inspect with [`rigor show-bleedingedge`](02-cli-reference.md#rigor-show-bleedingedge).
|
|
119
|
+
| `bleeding_edge` | Boolean / Array / Hash | `false` | Adopt the next major's queued diagnostic disciplines early ([ADR-50](../adr/50-release-engineering-and-stability-strategy.md) § WD2). `false` adopts none; `true` adopts the whole overlay; a list of feature ids adopts only those; `{ all: true, except: [ids] }` adopts all but the named. Orthogonal to `severity_profile`. Override it for a single run with [`rigor check --bleeding-edge[=ids]`](02-cli-reference.md#rigor-check) / `--no-bleeding-edge`. Inspect with [`rigor show-bleedingedge`](02-cli-reference.md#rigor-show-bleedingedge). |
|
|
95
120
|
|
|
96
121
|
### Dependency RBS discovery
|
|
97
122
|
|
|
@@ -128,11 +153,18 @@ explicitly with `bundler.bundle_path:`, or supply signatures another way:
|
|
|
128
153
|
| --- | --- | --- | --- |
|
|
129
154
|
| `cache.path` | String | `.rigor/cache` | Persistent cache directory. See [Caching](12-caching.md). |
|
|
130
155
|
| `cache.max_bytes` | Integer or `null` | `268435456` (256 MB) | LRU eviction cap for the cache directory; `null` disables eviction. See [Caching § Size and eviction](12-caching.md#size-and-eviction). |
|
|
131
|
-
| `
|
|
156
|
+
| `cache.validation` | String | `"auto"` | How the cache checks whether a file is unchanged: `auto` behaves as `digest` when a CI environment is detected and as `stat` otherwise; `stat` compares size + nanosecond timestamps + inode and only re-hashes a file whose stat moved; `digest` re-hashes every file's content every run. Both keep the content hash as the sole change authority — `stat` just skips the hash when the stat proves a file untouched. See [Caching § How a file is checked for changes](12-caching.md#how-a-file-is-checked-for-changes). The `RIGOR_STRICT_VALIDATION=1` environment variable forces `digest` for one run and wins over this key; `RIGOR_CI_DETECT=0` disables the CI detection. |
|
|
157
|
+
| `parallel.workers` | Integer | `0` | Parallel worker processes for per-file analysis (fork-based pool today; ADR-15); `0` is sequential. CLI `--workers` and `RIGOR_RACTOR_WORKERS` take precedence. Applies to `--incremental` re-checks as well as full runs. |
|
|
132
158
|
| `plugins_io.network` | String | `"disabled"` | Plugin network policy — `disabled` or `allowlist`. |
|
|
133
159
|
| `plugins_io.allowed_paths` | Array | `[]` | Filesystem paths plugins may read. |
|
|
134
160
|
| `plugins_io.allowed_url_hosts` | Array | `[]` | URL hosts plugins may fetch from when `network: allowlist`. |
|
|
135
161
|
|
|
162
|
+
### Reserved for other implementations
|
|
163
|
+
|
|
164
|
+
| Key | Type | Default | Meaning |
|
|
165
|
+
| --- | --- | --- | --- |
|
|
166
|
+
| `rigor_rs` | Hash | — | **Reserved; this implementation skips it.** Another Rigor implementation reads keys under this namespace, so one `.rigor.yml` can serve both. Rigor validates its shape at the schema level only — it never reads the value, and an invalid one is never a runtime error here. Leave it alone unless the tool that reads it tells you otherwise. |
|
|
167
|
+
|
|
136
168
|
## A worked example
|
|
137
169
|
|
|
138
170
|
```yaml
|