rigortype 0.2.9 → 0.3.0

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 (184) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/docs/handbook/03-narrowing.md +2 -1
  4. data/docs/handbook/04-tuples-and-shapes.md +7 -3
  5. data/docs/handbook/06-classes.md +18 -9
  6. data/docs/handbook/08-understanding-errors.md +1 -0
  7. data/docs/handbook/11-sig-gen.md +11 -1
  8. data/docs/handbook/appendix-mypy.md +4 -3
  9. data/docs/install.md +14 -6
  10. data/docs/manual/01-installation.md +98 -4
  11. data/docs/manual/02-cli-reference.md +49 -12
  12. data/docs/manual/03-configuration.md +34 -2
  13. data/docs/manual/04-diagnostics.md +23 -0
  14. data/docs/manual/07-plugins.md +4 -4
  15. data/docs/manual/09-editor-integration.md +4 -4
  16. data/docs/manual/11-ci.md +51 -0
  17. data/docs/manual/12-caching.md +65 -0
  18. data/lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb +9 -1
  19. data/lib/rigor/analysis/check_rules/dead_assignment_collector.rb +5 -3
  20. data/lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb +128 -0
  21. data/lib/rigor/analysis/check_rules/inferred_param_guard.rb +60 -0
  22. data/lib/rigor/analysis/check_rules/ivar_write_collector.rb +3 -2
  23. data/lib/rigor/analysis/check_rules/return_in_ensure_collector.rb +117 -0
  24. data/lib/rigor/analysis/check_rules/rule_ids.rb +125 -0
  25. data/lib/rigor/analysis/check_rules/rule_walk.rb +2 -1
  26. data/lib/rigor/analysis/check_rules/self_closedness_scanner.rb +2 -1
  27. data/lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb +283 -0
  28. data/lib/rigor/analysis/check_rules/unreachable_clause_collector.rb +10 -1
  29. data/lib/rigor/analysis/check_rules/void_value_use_collector.rb +93 -0
  30. data/lib/rigor/analysis/check_rules.rb +557 -95
  31. data/lib/rigor/analysis/dependency_recorder.rb +93 -9
  32. data/lib/rigor/analysis/dependency_source_inference/walker.rb +2 -1
  33. data/lib/rigor/analysis/incremental_session.rb +456 -51
  34. data/lib/rigor/analysis/path_expansion.rb +42 -0
  35. data/lib/rigor/analysis/plugin_fact_fingerprint.rb +188 -0
  36. data/lib/rigor/analysis/rule_catalog.rb +226 -1
  37. data/lib/rigor/analysis/run_cache_key.rb +68 -0
  38. data/lib/rigor/analysis/run_cache_probe.rb +72 -0
  39. data/lib/rigor/analysis/runner/diagnostic_aggregator.rb +181 -28
  40. data/lib/rigor/analysis/runner/pool_coordinator.rb +77 -15
  41. data/lib/rigor/analysis/runner/project_pre_passes.rb +95 -49
  42. data/lib/rigor/analysis/runner/run_snapshots.rb +9 -2
  43. data/lib/rigor/analysis/runner.rb +343 -68
  44. data/lib/rigor/analysis/severity_stamp.rb +43 -0
  45. data/lib/rigor/analysis/worker_session.rb +30 -2
  46. data/lib/rigor/bleeding_edge.rb +37 -8
  47. data/lib/rigor/builtins/regex_refinement.rb +36 -1
  48. data/lib/rigor/cache/descriptor.rb +88 -28
  49. data/lib/rigor/cache/file_digest.rb +158 -0
  50. data/lib/rigor/cache/incremental_snapshot.rb +41 -5
  51. data/lib/rigor/cache/rbs_descriptor.rb +56 -10
  52. data/lib/rigor/cache/store.rb +33 -3
  53. data/lib/rigor/ci_detector.rb +90 -0
  54. data/lib/rigor/cli/annotate_command.rb +15 -9
  55. data/lib/rigor/cli/baseline_command.rb +4 -1
  56. data/lib/rigor/cli/check_command.rb +212 -27
  57. data/lib/rigor/cli/coverage_command.rb +6 -1
  58. data/lib/rigor/cli/docs_command.rb +0 -30
  59. data/lib/rigor/cli/doctor_command.rb +163 -23
  60. data/lib/rigor/cli/lsp_command.rb +5 -0
  61. data/lib/rigor/cli/mcp_command.rb +5 -0
  62. data/lib/rigor/cli/plugins_command.rb +36 -6
  63. data/lib/rigor/cli/plugins_renderer.rb +44 -12
  64. data/lib/rigor/cli/probe_environment.rb +85 -0
  65. data/lib/rigor/cli/sig_gen_command.rb +36 -9
  66. data/lib/rigor/cli/skill_command.rb +1 -32
  67. data/lib/rigor/cli/trace_command.rb +5 -6
  68. data/lib/rigor/cli/type_of_command.rb +9 -8
  69. data/lib/rigor/cli/type_scan_command.rb +8 -8
  70. data/lib/rigor/cli.rb +15 -4
  71. data/lib/rigor/config_audit.rb +48 -2
  72. data/lib/rigor/configuration/severity_profile.rb +31 -0
  73. data/lib/rigor/configuration.rb +156 -8
  74. data/lib/rigor/environment/default_libraries.rb +35 -0
  75. data/lib/rigor/environment/rbs_loader.rb +164 -5
  76. data/lib/rigor/environment.rb +19 -27
  77. data/lib/rigor/inference/budget_trace.rb +77 -2
  78. data/lib/rigor/inference/closure_escape_analyzer.rb +14 -1
  79. data/lib/rigor/inference/def_handle.rb +23 -0
  80. data/lib/rigor/inference/def_node_resolver.rb +90 -0
  81. data/lib/rigor/inference/def_return_typer.rb +2 -1
  82. data/lib/rigor/inference/expression_typer.rb +361 -113
  83. data/lib/rigor/inference/method_dispatcher/data_folding.rb +30 -5
  84. data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +200 -0
  85. data/lib/rigor/inference/method_dispatcher/literal_string_folding.rb +22 -16
  86. data/lib/rigor/inference/method_dispatcher/member_shape_projection.rb +33 -0
  87. data/lib/rigor/inference/method_dispatcher/overload_selector.rb +11 -0
  88. data/lib/rigor/inference/method_dispatcher/rbs_dispatch.rb +42 -9
  89. data/lib/rigor/inference/method_dispatcher/receiver_affinity.rb +5 -0
  90. data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +28 -35
  91. data/lib/rigor/inference/method_dispatcher/struct_folding.rb +40 -8
  92. data/lib/rigor/inference/method_dispatcher.rb +57 -1
  93. data/lib/rigor/inference/mutation_widening.rb +42 -8
  94. data/lib/rigor/inference/narrowing.rb +127 -17
  95. data/lib/rigor/inference/parameter_inference_collector.rb +15 -0
  96. data/lib/rigor/inference/project_patched_scanner.rb +2 -1
  97. data/lib/rigor/inference/rbs_type_translator.rb +8 -1
  98. data/lib/rigor/inference/scope_indexer.rb +451 -36
  99. data/lib/rigor/inference/statement_evaluator.rb +64 -15
  100. data/lib/rigor/inference/struct_fold_safety.rb +48 -11
  101. data/lib/rigor/inference/synthetic_method_scanner.rb +15 -14
  102. data/lib/rigor/inference/void_origin.rb +25 -0
  103. data/lib/rigor/inference/void_tail_summary.rb +220 -0
  104. data/lib/rigor/language_server/completion_provider.rb +2 -1
  105. data/lib/rigor/language_server/document_symbol_provider.rb +2 -1
  106. data/lib/rigor/language_server/folding_range_provider.rb +2 -1
  107. data/lib/rigor/language_server/selection_range_provider.rb +2 -1
  108. data/lib/rigor/language_server/signature_help_provider.rb +2 -1
  109. data/lib/rigor/plugin/base.rb +9 -22
  110. data/lib/rigor/plugin/inflector.rb +12 -3
  111. data/lib/rigor/plugin/io_boundary.rb +5 -1
  112. data/lib/rigor/plugin/isolation.rb +81 -11
  113. data/lib/rigor/plugin/load_error.rb +10 -1
  114. data/lib/rigor/plugin/loader.rb +96 -14
  115. data/lib/rigor/plugin/node_rule_walk.rb +5 -3
  116. data/lib/rigor/plugin/registry.rb +32 -23
  117. data/lib/rigor/plugin.rb +26 -0
  118. data/lib/rigor/protection/mutator.rb +3 -2
  119. data/lib/rigor/reflection.rb +64 -0
  120. data/lib/rigor/runtime/jit.rb +128 -0
  121. data/lib/rigor/scope/discovery_index.rb +12 -2
  122. data/lib/rigor/scope.rb +122 -28
  123. data/lib/rigor/sig_gen/classification.rb +5 -1
  124. data/lib/rigor/sig_gen/generator.rb +38 -6
  125. data/lib/rigor/sig_gen/observation_collector.rb +4 -3
  126. data/lib/rigor/sig_gen/rbs_validity.rb +44 -0
  127. data/lib/rigor/sig_gen/renderer.rb +10 -0
  128. data/lib/rigor/sig_gen/write_result.rb +9 -4
  129. data/lib/rigor/sig_gen/writer.rb +24 -2
  130. data/lib/rigor/source/node_children.rb +116 -0
  131. data/lib/rigor/source/node_locator.rb +3 -1
  132. data/lib/rigor/source/node_walker.rb +4 -2
  133. data/lib/rigor/source.rb +1 -0
  134. data/lib/rigor/type/difference.rb +28 -24
  135. data/lib/rigor/type/hash_shape.rb +34 -10
  136. data/lib/rigor/version.rb +1 -1
  137. data/lib/rigortype.rb +24 -0
  138. data/plugins/rigor-actioncable/lib/rigor/plugin/actioncable/channel_discoverer.rb +4 -2
  139. data/plugins/rigor-actionmailer/lib/rigor/plugin/actionmailer/mailer_discoverer.rb +6 -4
  140. data/plugins/rigor-actionpack/lib/rigor/plugin/actionpack/controller_discoverer.rb +5 -3
  141. data/plugins/rigor-activejob/lib/rigor/plugin/activejob/job_discoverer.rb +4 -2
  142. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/analyzer.rb +3 -1
  143. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/model_discoverer.rb +4 -2
  144. data/plugins/rigor-activerecord/lib/rigor/plugin/activerecord/schema_parser.rb +4 -2
  145. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/analyzer.rb +3 -1
  146. data/plugins/rigor-activestorage/lib/rigor/plugin/activestorage/attachment_discoverer.rb +4 -2
  147. data/plugins/rigor-dry-types/lib/rigor/plugin/dry_types.rb +38 -6
  148. data/plugins/rigor-factorybot/lib/rigor/plugin/factorybot/factory_discoverer.rb +3 -1
  149. data/plugins/rigor-hanami/lib/rigor/plugin/hanami/action_checker.rb +3 -1
  150. data/plugins/rigor-mangrove/lib/rigor/plugin/mangrove.rb +10 -0
  151. data/plugins/rigor-minitest/lib/rigor/plugin/minitest.rb +11 -0
  152. data/plugins/rigor-pundit/lib/rigor/plugin/pundit/policy_discoverer.rb +3 -1
  153. data/plugins/rigor-rails/lib/rigor-rails.rb +11 -12
  154. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/grape_api_discoverer.rb +3 -1
  155. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/helper_discoverer.rb +3 -1
  156. data/plugins/rigor-rails-routes/lib/rigor/plugin/rails_routes/routes_parser.rb +7 -5
  157. data/plugins/rigor-rbs-inline/lib/rigor/plugin/rbs_inline.rb +83 -9
  158. data/plugins/rigor-rbs-inline/lib/rigor-rbs-inline.rb +9 -5
  159. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/let_scope_index.rb +3 -1
  160. data/plugins/rigor-rspec/lib/rigor/plugin/rspec/scope_walker.rb +3 -1
  161. data/plugins/rigor-rspec/lib/rigor/plugin/rspec.rb +11 -0
  162. data/plugins/rigor-rspec-rails/lib/rigor/plugin/rspec_rails/http_status_codes.rb +4 -1
  163. data/plugins/rigor-sidekiq/lib/rigor/plugin/sidekiq/worker_discoverer.rb +4 -2
  164. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet/catalog_walker.rb +3 -1
  165. data/plugins/rigor-sorbet/lib/rigor/plugin/sorbet.rb +74 -14
  166. data/sig/prism_node_children.rbs +9 -0
  167. data/sig/rigor/inference.rbs +7 -0
  168. data/sig/rigor/plugin/base.rbs +2 -3
  169. data/sig/rigor/reflection.rbs +1 -0
  170. data/sig/rigor/scope.rbs +12 -1
  171. data/skills/rigor-ci-setup/SKILL.md +10 -0
  172. data/skills/rigor-editor-setup/SKILL.md +11 -0
  173. data/skills/rigor-next-steps/SKILL.md +23 -2
  174. data/skills/rigor-plugin-author/SKILL.md +3 -3
  175. data/skills/rigor-plugin-author/references/02-walker-and-types.md +2 -2
  176. data/skills/rigor-plugin-review/SKILL.md +2 -2
  177. data/skills/rigor-plugin-review/references/01-best-practices-checklist.md +5 -4
  178. data/skills/rigor-project-init/SKILL.md +29 -3
  179. data/skills/rigor-project-init/references/01-detect.md +1 -1
  180. data/skills/rigor-project-init/references/02-configure.md +39 -5
  181. data/skills/rigor-project-init/references/03-baseline-and-bugs.md +20 -0
  182. data/skills/rigor-project-init/references/05-jit-performance.md +125 -0
  183. metadata +42 -24
  184. data/lib/rigor/cli/ci_detector.rb +0 -89
@@ -0,0 +1,125 @@
1
+ # Reference 05 — JIT and run speed (YJIT / ZJIT)
2
+
3
+ Operational, not part of onboarding proper: how Rigor uses a Ruby JIT to
4
+ speed up analysis, how to tell whether it is active in your install, and the
5
+ trade-off (and break-even point) if you want to override the default. Read
6
+ this when a project is large enough that `rigor check` wall time matters —
7
+ Rails monorepos especially. On a small project you can ignore it entirely:
8
+ Rigor already does the right thing with no configuration.
9
+
10
+ ## TL;DR
11
+
12
+ - **You usually do nothing.** Rigor enables YJIT automatically once a run has
13
+ been going long enough to be worth it, and leaves it off for short runs
14
+ where it would only add warm-up cost. This is on by default.
15
+ - **Break-even is ~5 seconds.** A JIT pays for its warm-up only on longer
16
+ runs; below it, JIT-on is *slower*. Rigor's 5-second deadline is set at
17
+ that crossover.
18
+ - **YJIT, not ZJIT.** Ruby 4.0 ships both JITs, but YJIT is faster for Rigor's
19
+ workload — measurably so on every run large enough for a JIT to help. Rigor
20
+ uses YJIT; there is no reason to force ZJIT.
21
+
22
+ ## How Rigor uses a JIT
23
+
24
+ `rigor check` and `rigor coverage` arm a background timer at the start of a
25
+ run. If the run is still going after ~5 seconds, YJIT is switched on for the
26
+ remainder; a run that finishes first never pays any JIT cost. So:
27
+
28
+ - A quick check (a small project, or a warm cache hit) runs on the plain
29
+ interpreter — no warm-up penalty.
30
+ - A long cold analysis of a large project gets YJIT for its dominant tail,
31
+ where the speed-up more than repays the warm-up.
32
+
33
+ Diagnostics and their counts are identical whether or not the JIT engages —
34
+ a JIT changes wall time only, never results.
35
+
36
+ The long-running servers `rigor lsp` and `rigor mcp` turn YJIT on at start
37
+ instead, since they always run long.
38
+
39
+ ## Is a JIT available in my install?
40
+
41
+ The deferred-YJIT feature only helps if the Ruby your `rigor` runs on was
42
+ built with YJIT support. Rigor is installed standalone (see the manual's
43
+ Installing Rigor chapter: `rigor docs manual/01-installation`), so this is a
44
+ property of *that* Ruby, which may differ from your project's Ruby.
45
+
46
+ Check the Ruby that runs `rigor`:
47
+
48
+ ```sh
49
+ ruby --yjit -e 'require "rbconfig"; puts "YJIT: #{RbConfig::CONFIG["YJIT_SUPPORT"]}"; puts "ZJIT: #{RbConfig::CONFIG["ZJIT_SUPPORT"]}"'
50
+ # YJIT: yes → the deferred-YJIT engages automatically on long runs
51
+ # YJIT: no → the feature is a silent no-op; runs use the interpreter
52
+ ```
53
+
54
+ - Most prebuilt CRuby 3.3+ (mise / rbenv / asdf, the recommended install
55
+ channels) ship with YJIT built in but **not** ZJIT — a prebuilt
56
+ mise Ruby 4.0, for example, reports `YJIT: yes` / `ZJIT: no`, because
57
+ ZJIT needs `rustc` at build time and the prebuilt binary omits it. That
58
+ is exactly the configuration Rigor wants: YJIT is the faster JIT for
59
+ Rigor (see the YJIT-vs-ZJIT section below), so a missing ZJIT costs you
60
+ nothing.
61
+ - The Nix flake package of Rigor bundles a Ruby with **both** JITs; that
62
+ is the only common install where `ZJIT: yes` — and Rigor still uses
63
+ YJIT there.
64
+ - A YJIT-less Ruby is not an error — Rigor just runs interpreted, correctly.
65
+
66
+ ## Overriding the default
67
+
68
+ Three environment variables, documented in the CLI reference's
69
+ "Environment variables" section (`rigor docs manual/02-cli-reference`):
70
+
71
+ | Want | Do |
72
+ | --- | --- |
73
+ | Force YJIT on for the **whole** run (including the first 5 s) | `RUBYOPT="--yjit" rigor check …` |
74
+ | Turn Rigor's JIT off entirely | `RIGOR_DISABLE_YJIT=1 rigor check …` |
75
+ | Change the deadline (advanced) | `RIGOR_YJIT_DEADLINE=<seconds> rigor check …` |
76
+
77
+ When would you override?
78
+
79
+ - **Force-on** helps only if *every* run you care about is long (a big
80
+ monorepo in CI where even the fast path is > 5 s). On mixed workloads the
81
+ default deadline is better — it protects your quick local re-checks.
82
+ - **Off** is the escape hatch if a JIT ever misbehaves on your platform, or to
83
+ get a clean interpreter baseline when measuring.
84
+
85
+ ## Why the ~5-second break-even (the trade-off)
86
+
87
+ A JIT compiles hot code to machine code, which costs time up front and repays
88
+ it over the rest of the run. On a short run the compilation never amortizes,
89
+ so JIT-on loses. Measured cold `rigor check`, by project size:
90
+
91
+ | run size | interpreter | YJIT | effect |
92
+ | --- | --- | --- | --- |
93
+ | ~1.6 s (small lib) | baseline | **+67 %** | JIT-on loses badly |
94
+ | ~4 s (medium lib) | baseline | ~break-even | a wash |
95
+ | ~8 s | baseline | **−13 %** | JIT-on wins |
96
+ | ~19 s (Rails monorepo) | baseline | **−20 %** | wins more |
97
+ | ~17 s (large Rails app) | baseline | **−28 %** | biggest win |
98
+
99
+ The deadline parks the enable point just past the loss zone: runs that finish
100
+ before ~5 s never pay warm-up; longer runs collect the win on their tail.
101
+
102
+ ## YJIT vs ZJIT (Ruby 4.0)
103
+
104
+ Ruby 4.0 ships a second JIT, **ZJIT** (a newer method-based JIT;
105
+ [upstream docs](https://docs.ruby-lang.org/en/master/jit/zjit_md.html)). It
106
+ is real and correctness-safe on Rigor (identical diagnostics), but **slower
107
+ than YJIT for Rigor's workload** at Ruby 4.0. Measured cold, on the runs where
108
+ a JIT helps at all:
109
+
110
+ | target | YJIT vs interpreter | ZJIT vs interpreter | ZJIT vs YJIT |
111
+ | --- | --- | --- | --- |
112
+ | ~8 s | −13 % | −4 % | +10 % |
113
+ | ~19 s (monorepo) | −20 % | −13 % | +10 % |
114
+ | ~17 s (large app) | −28 % | −14 % | +21 % |
115
+
116
+ YJIT wins on every workload large enough to warrant a JIT; ZJIT's peak
117
+ speed-up is roughly half. ZJIT only edges YJIT on tiny runs — the zone where
118
+ you want no JIT at all. **Do not force ZJIT** (`RUBYOPT="--zjit"`) for Rigor;
119
+ the automatic YJIT is faster. Full measurement + methodology (a
120
+ contributor-side note, web only):
121
+ <https://github.com/rigortype/rigor/blob/master/docs/notes/20260714-jit-evaluation-yjit-zjit-ruby40.md>.
122
+
123
+ This verdict is Ruby-4.0-specific; ZJIT is younger than YJIT and improving, so
124
+ it may close the gap in a later Ruby. Until then YJIT is the right default —
125
+ which is what Rigor already does.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rigortype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rigor contributors
@@ -129,26 +129,6 @@ dependencies:
129
129
  - - "<"
130
130
  - !ruby/object:Gem::Version
131
131
  version: '1.0'
132
- - !ruby/object:Gem::Dependency
133
- name: parallel_tests
134
- requirement: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '4.0'
139
- - - "<"
140
- - !ruby/object:Gem::Version
141
- version: '6.0'
142
- type: :development
143
- prerelease: false
144
- version_requirements: !ruby/object:Gem::Requirement
145
- requirements:
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- version: '4.0'
149
- - - "<"
150
- - !ruby/object:Gem::Version
151
- version: '6.0'
152
132
  - !ruby/object:Gem::Dependency
153
133
  name: rake
154
134
  requirement: !ruby/object:Gem::Requirement
@@ -269,8 +249,13 @@ dependencies:
269
249
  - - "<"
270
250
  - !ruby/object:Gem::Version
271
251
  version: '4.0'
272
- description: Rigor is a CLI-first static analyzer for Ruby applications that prioritizes
273
- type inference, clean application code, and zero runtime dependencies.
252
+ description: 'Rigor is a CLI-first static analyzer for Ruby applications that prioritizes
253
+ type inference, clean application code, and zero runtime dependencies. Rigor is
254
+ a standalone tool, not a library: install it independently rather than adding it
255
+ to your application''s Gemfile. It runs on Ruby 4.0 while your project keeps its
256
+ own Ruby, and it reads your project as data rather than loading it, so a Gemfile
257
+ entry only constrains your application''s Ruby and dependency resolution. Installation
258
+ channels (mise, asdf, gem install, container, Nix): https://github.com/rigortype/rigor/blob/master/docs/install.md'
274
259
  email:
275
260
  - maintainers@example.invalid
276
261
  executables:
@@ -410,11 +395,17 @@ files:
410
395
  - lib/rigor/analysis/check_rules.rb
411
396
  - lib/rigor/analysis/check_rules/always_truthy_condition_collector.rb
412
397
  - lib/rigor/analysis/check_rules/dead_assignment_collector.rb
398
+ - lib/rigor/analysis/check_rules/duplicate_hash_key_collector.rb
399
+ - lib/rigor/analysis/check_rules/inferred_param_guard.rb
413
400
  - lib/rigor/analysis/check_rules/ivar_write_collector.rb
414
401
  - lib/rigor/analysis/check_rules/main_pass_collector.rb
402
+ - lib/rigor/analysis/check_rules/return_in_ensure_collector.rb
403
+ - lib/rigor/analysis/check_rules/rule_ids.rb
415
404
  - lib/rigor/analysis/check_rules/rule_walk.rb
416
405
  - lib/rigor/analysis/check_rules/self_closedness_scanner.rb
406
+ - lib/rigor/analysis/check_rules/shadowed_rescue_collector.rb
417
407
  - lib/rigor/analysis/check_rules/unreachable_clause_collector.rb
408
+ - lib/rigor/analysis/check_rules/void_value_use_collector.rb
418
409
  - lib/rigor/analysis/dependency_recorder.rb
419
410
  - lib/rigor/analysis/dependency_source_inference.rb
420
411
  - lib/rigor/analysis/dependency_source_inference/boundary_cross_reporter.rb
@@ -428,9 +419,13 @@ files:
428
419
  - lib/rigor/analysis/fact_store.rb
429
420
  - lib/rigor/analysis/incremental.rb
430
421
  - lib/rigor/analysis/incremental_session.rb
422
+ - lib/rigor/analysis/path_expansion.rb
423
+ - lib/rigor/analysis/plugin_fact_fingerprint.rb
431
424
  - lib/rigor/analysis/project_scan.rb
432
425
  - lib/rigor/analysis/result.rb
433
426
  - lib/rigor/analysis/rule_catalog.rb
427
+ - lib/rigor/analysis/run_cache_key.rb
428
+ - lib/rigor/analysis/run_cache_probe.rb
434
429
  - lib/rigor/analysis/run_stats.rb
435
430
  - lib/rigor/analysis/runner.rb
436
431
  - lib/rigor/analysis/runner/diagnostic_aggregator.rb
@@ -438,6 +433,7 @@ files:
438
433
  - lib/rigor/analysis/runner/project_pre_passes.rb
439
434
  - lib/rigor/analysis/runner/run_snapshots.rb
440
435
  - lib/rigor/analysis/self_call_resolution_recorder.rb
436
+ - lib/rigor/analysis/severity_stamp.rb
441
437
  - lib/rigor/analysis/worker_session.rb
442
438
  - lib/rigor/ast.rb
443
439
  - lib/rigor/ast/type_node.rb
@@ -448,6 +444,7 @@ files:
448
444
  - lib/rigor/builtins/regex_refinement.rb
449
445
  - lib/rigor/builtins/static_return_refinements.rb
450
446
  - lib/rigor/cache/descriptor.rb
447
+ - lib/rigor/cache/file_digest.rb
451
448
  - lib/rigor/cache/incremental_snapshot.rb
452
449
  - lib/rigor/cache/rbs_cache_producer.rb
453
450
  - lib/rigor/cache/rbs_class_ancestor_table.rb
@@ -458,12 +455,12 @@ files:
458
455
  - lib/rigor/cache/rbs_environment_marshal_patch.rb
459
456
  - lib/rigor/cache/rbs_known_class_names.rb
460
457
  - lib/rigor/cache/store.rb
458
+ - lib/rigor/ci_detector.rb
461
459
  - lib/rigor/cli.rb
462
460
  - lib/rigor/cli/annotate_command.rb
463
461
  - lib/rigor/cli/baseline_command.rb
464
462
  - lib/rigor/cli/check_command.rb
465
463
  - lib/rigor/cli/check_runner_factory.rb
466
- - lib/rigor/cli/ci_detector.rb
467
464
  - lib/rigor/cli/command.rb
468
465
  - lib/rigor/cli/coverage_command.rb
469
466
  - lib/rigor/cli/coverage_mutation.rb
@@ -486,6 +483,7 @@ files:
486
483
  - lib/rigor/cli/plugins_command.rb
487
484
  - lib/rigor/cli/plugins_renderer.rb
488
485
  - lib/rigor/cli/prism_colorizer.rb
486
+ - lib/rigor/cli/probe_environment.rb
489
487
  - lib/rigor/cli/protection_fork_scan.rb
490
488
  - lib/rigor/cli/protection_renderer.rb
491
489
  - lib/rigor/cli/protection_report.rb
@@ -512,6 +510,7 @@ files:
512
510
  - lib/rigor/environment/bundle_sig_discovery.rb
513
511
  - lib/rigor/environment/class_registry.rb
514
512
  - lib/rigor/environment/constant_type_cache_holder.rb
513
+ - lib/rigor/environment/default_libraries.rb
515
514
  - lib/rigor/environment/hkt_registry_holder.rb
516
515
  - lib/rigor/environment/lockfile_resolver.rb
517
516
  - lib/rigor/environment/missing_gem_constant_index.rb
@@ -553,6 +552,8 @@ files:
553
552
  - lib/rigor/inference/builtins/time_catalog.rb
554
553
  - lib/rigor/inference/closure_escape_analyzer.rb
555
554
  - lib/rigor/inference/coverage_scanner.rb
555
+ - lib/rigor/inference/def_handle.rb
556
+ - lib/rigor/inference/def_node_resolver.rb
556
557
  - lib/rigor/inference/def_return_typer.rb
557
558
  - lib/rigor/inference/dynamic_origin.rb
558
559
  - lib/rigor/inference/expression_typer.rb
@@ -609,6 +610,8 @@ files:
609
610
  - lib/rigor/inference/synthetic_method.rb
610
611
  - lib/rigor/inference/synthetic_method_index.rb
611
612
  - lib/rigor/inference/synthetic_method_scanner.rb
613
+ - lib/rigor/inference/void_origin.rb
614
+ - lib/rigor/inference/void_tail_summary.rb
612
615
  - lib/rigor/language_server.rb
613
616
  - lib/rigor/language_server/buffer_resolution.rb
614
617
  - lib/rigor/language_server/buffer_table.rb
@@ -664,6 +667,7 @@ files:
664
667
  - lib/rigor/rbs_extended/hkt_directives.rb
665
668
  - lib/rigor/rbs_extended/reporter.rb
666
669
  - lib/rigor/reflection.rb
670
+ - lib/rigor/runtime/jit.rb
667
671
  - lib/rigor/scope.rb
668
672
  - lib/rigor/scope/discovery_index.rb
669
673
  - lib/rigor/sig_gen.rb
@@ -674,6 +678,7 @@ files:
674
678
  - lib/rigor/sig_gen/observation_collector.rb
675
679
  - lib/rigor/sig_gen/observed_call.rb
676
680
  - lib/rigor/sig_gen/path_mapper.rb
681
+ - lib/rigor/sig_gen/rbs_validity.rb
677
682
  - lib/rigor/sig_gen/renderer.rb
678
683
  - lib/rigor/sig_gen/type_elaborator.rb
679
684
  - lib/rigor/sig_gen/write_result.rb
@@ -682,6 +687,7 @@ files:
682
687
  - lib/rigor/source.rb
683
688
  - lib/rigor/source/constant_path.rb
684
689
  - lib/rigor/source/literals.rb
690
+ - lib/rigor/source/node_children.rb
685
691
  - lib/rigor/source/node_locator.rb
686
692
  - lib/rigor/source/node_walker.rb
687
693
  - lib/rigor/testing.rb
@@ -725,6 +731,7 @@ files:
725
731
  - lib/rigor/type_node/union.rb
726
732
  - lib/rigor/value_semantics.rb
727
733
  - lib/rigor/version.rb
734
+ - lib/rigortype.rb
728
735
  - plugins/rigor-actioncable/lib/rigor-actioncable.rb
729
736
  - plugins/rigor-actioncable/lib/rigor/plugin/actioncable.rb
730
737
  - plugins/rigor-actioncable/lib/rigor/plugin/actioncable/analyzer.rb
@@ -850,6 +857,7 @@ files:
850
857
  - plugins/rigor-statesman/lib/rigor/plugin/statesman.rb
851
858
  - plugins/rigor-typescript-utility-types/lib/rigor-typescript-utility-types.rb
852
859
  - plugins/rigor-typescript-utility-types/lib/rigor/plugin/typescript_utility_types.rb
860
+ - sig/prism_node_children.rbs
853
861
  - sig/rigor.rbs
854
862
  - sig/rigor/analysis/baseline.rbs
855
863
  - sig/rigor/analysis/check_rules/always_truthy_condition_collector.rbs
@@ -911,6 +919,7 @@ files:
911
919
  - skills/rigor-project-init/references/02-configure.md
912
920
  - skills/rigor-project-init/references/03-baseline-and-bugs.md
913
921
  - skills/rigor-project-init/references/04-sig-uplift.md
922
+ - skills/rigor-project-init/references/05-jit-performance.md
914
923
  - skills/rigor-protection-uplift/SKILL.md
915
924
  - skills/rigor-rbs-setup/SKILL.md
916
925
  - skills/rigor-upgrade/SKILL.md
@@ -922,6 +931,15 @@ metadata:
922
931
  source_code_uri: https://github.com/rigortype/rigor
923
932
  documentation_uri: https://github.com/rigortype/rigor/tree/master/docs
924
933
  rubygems_mfa_required: 'true'
934
+ post_install_message: |
935
+ Rigor installs as a standalone CLI, not a project dependency. Run `rigor check app lib` from your
936
+ project root — no `bundle exec`.
937
+
938
+ If this came from `bundle add rigortype` or a Gemfile entry, remove it: Rigor runs on its own Ruby
939
+ and analyses your project from the outside, so in a Gemfile it constrains your application's Ruby
940
+ and dependency resolution without giving you anything. Per-project version pinning without that
941
+ cost, plus every other channel, is documented in
942
+ https://github.com/rigortype/rigor/blob/master/docs/install.md
925
943
  rdoc_options: []
926
944
  require_paths:
927
945
  - lib
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rigor
4
- class CLI
5
- # Runtime CI-environment detection (ADR-51 WD7), modelled on `OndraM/ci-detector` (the library PHPStan uses). Reads
6
- # the well-known environment variables a CI provider sets and returns the matching {Platform}, classifying it into a
7
- # **tier** that decides how `rigor check` surfaces diagnostics there:
8
- #
9
- # :native_stdout — Rigor has a native format that renders purely from
10
- # stdout, so it is auto-emitted on top of the human
11
- # output (GitHub Actions → `github`, TeamCity →
12
- # `teamcity`). These are the first-class platforms.
13
- # :native_artifact — Rigor has a native format but it needs a CI-wired
14
- # report artifact, not stdout (GitLab CI → `gitlab`).
15
- # First-class, but Rigor only *hints* the format.
16
- # :reviewdog — no native Rigor format; second-class, routed through
17
- # reviewdog (`checkstyle`/`sarif`) or `junit`. Hint
18
- # only.
19
- #
20
- # Detection is a pure function of the environment hash, so it is fully testable; the CLI passes `ENV`.
21
- # `RIGOR_CI_DETECT=0` (or `false`/`no`) disables it globally — the seam the spec suite uses for determinism.
22
- module CiDetector
23
- Platform = Struct.new(:id, :name, :format, :tier, keyword_init: true) do
24
- def native_stdout? = tier == :native_stdout
25
- def native_artifact? = tier == :native_artifact
26
- def reviewdog? = tier == :reviewdog
27
- end
28
-
29
- # The detection table, ordered most-specific first so the generic `CI=true` catch-all is last (a provider that
30
- # also sets `CI` is still recognised by its own variable). `match` is `:truthy` (value in 1/true/yes/on),
31
- # `:present` (variable set non-empty), or `:equals`.
32
- PROVIDERS = [
33
- { id: "github-actions", name: "GitHub Actions", format: "github", tier: :native_stdout,
34
- var: "GITHUB_ACTIONS", match: :truthy },
35
- { id: "gitlab", name: "GitLab CI", format: "gitlab", tier: :native_artifact,
36
- var: "GITLAB_CI", match: :truthy },
37
- { id: "teamcity", name: "TeamCity", format: "teamcity", tier: :native_stdout,
38
- var: "TEAMCITY_VERSION", match: :present },
39
- { id: "circleci", name: "CircleCI", format: nil, tier: :reviewdog,
40
- var: "CIRCLECI", match: :truthy },
41
- { id: "jenkins", name: "Jenkins", format: nil, tier: :reviewdog,
42
- var: "JENKINS_URL", match: :present },
43
- { id: "travis", name: "Travis CI", format: nil, tier: :reviewdog,
44
- var: "TRAVIS", match: :truthy },
45
- { id: "appveyor", name: "AppVeyor", format: nil, tier: :reviewdog,
46
- var: "APPVEYOR", match: :truthy },
47
- { id: "azure-pipelines", name: "Azure Pipelines", format: nil, tier: :reviewdog,
48
- var: "TF_BUILD", match: :present },
49
- { id: "bitbucket", name: "Bitbucket Pipelines", format: nil, tier: :reviewdog,
50
- var: "BITBUCKET_BUILD_NUMBER", match: :present },
51
- { id: "buildkite", name: "Buildkite", format: nil, tier: :reviewdog,
52
- var: "BUILDKITE", match: :truthy },
53
- { id: "drone", name: "Drone CI", format: nil, tier: :reviewdog,
54
- var: "DRONE", match: :truthy },
55
- { id: "semaphore", name: "Semaphore", format: nil, tier: :reviewdog,
56
- var: "SEMAPHORE", match: :truthy },
57
- { id: "codeship", name: "Codeship", format: nil, tier: :reviewdog,
58
- var: "CI_NAME", match: :equals, value: "codeship" },
59
- { id: "ci", name: "CI", format: nil, tier: :reviewdog,
60
- var: "CI", match: :truthy }
61
- ].freeze
62
-
63
- module_function
64
-
65
- # Returns the detected {Platform}, or nil when no CI is recognised or detection is disabled via `RIGOR_CI_DETECT`.
66
- def detect(env = ENV)
67
- return nil if disabled?(env)
68
-
69
- row = PROVIDERS.find { |provider| matches?(env, provider) }
70
- return nil if row.nil?
71
-
72
- Platform.new(id: row[:id], name: row[:name], format: row[:format], tier: row[:tier])
73
- end
74
-
75
- def disabled?(env)
76
- %w[0 false no off].include?(env["RIGOR_CI_DETECT"].to_s.strip.downcase)
77
- end
78
-
79
- def matches?(env, provider)
80
- value = env[provider[:var]].to_s.strip
81
- case provider[:match]
82
- when :truthy then %w[1 true yes on].include?(value.downcase)
83
- when :present then !value.empty?
84
- when :equals then value.downcase == provider[:value]
85
- end
86
- end
87
- end
88
- end
89
- end